shell编程之进阶

一、特殊变量

1、几个常见的特殊变量

特殊位置变量

$_ 获取上一条命令的最后一个参数
$0 文件名
$# 参数的个数
$? a、shell执行结果成果为0 b、脚本中exit退出码 c、接受的函数的返回值
$* *代表数字,第几个参数,当超过定义的参数个数,不会显示 $(xx)两位数得带括号
$(($1+$2)) 可以对括号里面的参数进行计算当成一个变量
$* 获取当前shell所传递的参数(在执行文件时,在文件名后面跟的参数),对于加了引号的$*来说,会将所有的参数看作为一体的
$@ 获取当前shell所传递的参数,对于加了引号的,没有任何影响
$$ shell脚本的pid
$! 上一个后台工作的pid

shell脚本
在这里插入图片描述
执行
在这里插入图片描述
结果

在这里插入图片描述

二、内部命令

1、shift

跳过接下来的参数
在这里插入图片描述

2、echo

是输出命令,常见的参数:

  • -n:不换行输出
  • -e:解析转义字符
  • 常见的转义字符
    在这里插入图片描述

3、exec

在不创建子进程的情况下,转义执行指定命令,指定命令完成也就终止了。如下图所示
在开始pstree显示两个bash,exec在不创建新的bash的情况下执行了命令就退出去了,直接断了一个bash,再用pstree显示就只剩一个bash
在这里插入图片描述

4、read

-p:提示用户输入并接收用户键盘的输入
在这里插入图片描述

5、exit

退出shell程序的一个返回值,可以自己设施,用echo $?来查
在这里插入图片描述

6、获取路径名和文件名

dirname :获取目录路径
basename :获取文件名称
在这里插入图片描述

三、脚本字串的获取

1、变量的输出

  • 常见
  • a、x:(x表示数字)从x+1处取字符
  • b、/x/y:替换将x替换为y
  • c、#:从单词后取且必须是从第一个开始,支持通配(w*d)
  • d、%:从单词前取必须是从最后一个开始,支持通配(w*d)
变量名 释义
echo $A 输出变量A的值
echo ${A} 输出变量A的值
echo ${#A} 获取变量A的长度
echo ${A:x} 在变量A中从x+1的位置取字符串到结尾
echo ${A:x :y} 从变量A中的x+1位置取y个字符串
echo ${A#word} 从开头找word单词取word之后的字符串
echo ${A#w*d] 最短匹配,依旧从开始找开头必须是w
echo ${A##w*d} 最长匹配在这里插入图片描述
echo ${A%word} 从后往前取d为结尾在这里插入图片描述
echo ${A%e*d} 最短匹配
echo ${A%%e*d} 最长匹配
echo ${A/e/x} 将第一个e替换为x
echo ${A//e/x} 所有的全部替换在这里插入图片描述

2、统计字符串的长度

a、常见的四种

1、echo ${#A}
2、expr length “$a”
3、echo ${A} |wc -l
4、echo “$A” |awk ‘{print length}’

[root@lianxi shell.test]# A=linux
[root@lianxi shell.test]# echo ${
    
    #A}
5
[root@lianxi shell.test]# expr length "$A"
5
[root@lianxi shell.test]# echo ${
    
    A} |wc -L
5
[root@lianxi shell.test]# echo "$A" |awk '{print length}'
5

b、练习

(1)取出一句话中小于3的字符串

[root@lianxi shell.test]cat min3.sh
row="this is aaaaaaaaaaaa"
for i in $row
do
    if [ ${#i} -lt 3 ]
    then 
        echo $i
    fi
done
[root@lianxi shell.test]sh min3.sh
is

(2)批量修改文件名

[root@lianxi shell.test] cat mvfilename.sh 

for i in `ls ~/ooo/*` #遍历ooo目录下面的文件
do
    mv $i ${i/f/y}
done
[root@lianxi ooo]ls
_  etc  lyile.zip  one  yile04  yile05  yile06  yile07  yile08  yile09  yile10

3、特殊变量

如果没有定义或者已被定义还会被重新赋值,常见的四种:
1、echo ${name:-zhangsan}:表示如果没有被赋值的话会将张三输出,但是并不是把张三赋值给了name变量

[root@lianxi ~]echo ${name:-zhangsan}
zhangsan
[root@lianxi ~] echo $name#下次输出变量name的时候依旧为空,只是临时的用一下

2、echo ${name:=zhangsan}:如果没有被复制的话会给其赋值为张三

[root@lianxi ~]echo ${name:=zhangsan}
zhangsan
[root@lianxi ~] echo $name#是将值赋给了那么,那么再次输出会将zhangsan输出
zhangsan

3、echo ${name+xxxxx}:如果变量有值,则临时将xxxxx作为name的值输出,并不是将值赋给了变量

[root@lianxi ~]echo $name# 变量的原值
zhangsan
[root@lianxi ~] echo ${name:+xxxxx}#输出并不是原值,临时的值
xxxxx
[root@lianxi ~]echo $name#又是原值
zhangsan

4、echo ${myname?tishi}:如果变量没有值,则输出提示

[root@lianxi ~]echo $myname#变量值为空

[root@lianxi ~]echo ${myname:?xxxxx}#输出提示xxxxxx
-bash: myname: xxxxx

练习1、:删除~/ooo下的前七天文件

[root@lianxi ooo]ls#ooo下的文件
_  etc  lyile.zip  one  yile04  yile05  yile06  yile07  yile08  yile09  yile10
[root@lianxi shell.test] cat delete.sh 
dir=~/ooo/*
find ${dir:-~/rubbish} -mtime +7 |xargs rm -rf#为了防止出错,如果$dir为空,则用~/rubbish目录
[root@lianxi shell.test] sh delete.sh #执行
[root@lianxi ooo] ls# 全部为空
[root@lianxi ooo] 

脚本文件还可以这样写
dir=~/ooo/*
find ${dir:-~/rubbish} -mtime +7  -exec rm -rf {
    
    } \;

练习二创建带有时间戳的文件

[root@lianxi ooo] touch `date "+%Y%m%d"`.txt
[root@lianxi ooo] ls
20210304.txt  file.txt

四、数值运算

几种常见的运算方法

  • (())
  • expr
  • bc
  • []
  • declare
  • awk

1、(())

a、可以加+ 减- 乘* 除/ 取余%幂运算**,赋值

[root@lianxi ooo] echo $((1+1))#加
2
[root@lianxi ooo] echo $((1-1))#减
0
[root@lianxi ooo]  echo $((1*2))#乘
2
[root@lianxi ooo]  echo $((1/2))#除
0
[root@lianxi ooo] echo $((1%2))#取余
1
[root@lianxi ooo] echo $((2**2))#幂运算
4

b、数值字符串的比较

  • 对为1,错为0
  • 字符串用=来比较
  • 数值用==来比较
[root@lianxi ooo]  echo $((1>2))
0
[root@lianxi ooo] echo $((1<2))
1
[root@lianxi ooo] echo $((aaa=sss))
0
[root@lianxi ooo] echo $((2==1))
0

c 、可以加逻辑判断

[root@lianxi ooo] echo $((8>1&&1==1))#正确
1

2、let

let n++
let也就等于(())

[root@lianxi shell.test] cat let.sh
n=1
let n++
echo $n
[root@lianxi shell.test] sh let.sh
2

练习1:监控apach,如果询问两次失误则报警

 [root@lianxi shell.test] cat jiankong.sh 
n=0
while ((n<2))
do
    curl 192.168.42.145 >/dev/null 2>&1
          if [ $? -ne 0 ]
          then
                        let n++
               echo "坏了.."
           fi
            sleep 3
    done
    echo "wrong"
[root@lianxi shell.test] sh jiankong.sh 
坏了..
^C

3、expr

(1)、整数运算(运算符号要加空格)
(2)、字符串匹配 (:来比较)(=也可以)也要加空格
(3)、字符串长度的计算

[root@lianxi shell.test] expr 1 + 1 #整数运算
2
[root@lianxi shell.test] expr a = 1#字符串匹配
0
[root@lianxi shell.test] echo $?#匹配不成功
1
[root@lianxi shell.test] expr a = a#字符串匹配
1
[root@lianxi shell.test] echo $?#匹配成功
0
[root@lianxi shell.test] expr ddd : www
0
[root@lianxi shell.test] echo $?
1
[root@lianxi shell.test] name=ssss# 计算字符串长度
[root@lianxi shell.test] expr length $name
4

练习1:判断输出是否为数字
可以用expr的特性,让输入的字符和数字相加,判断返回值是否为0,0为数字,其他为非数字

[root@lianxi shell.test] cat panduan.sh
read -p "please enter any:" one
expr $one + 1 >/dev/null 2>&1
if [ $? -eq 0 ]
then
    echo "shuzi"
else
    echo "bushi"
fi
[root@lianxi shell.test] sh panduan.sh
please enter any:1
shuzi
[root@lianxi shell.test] sh panduan.sh
please enter any:d
bushi

五、条件判断

常见的条件判断有四种分别是:

  • test:符号两边要有空格,用-eq
  • [ ]:括号两端需要空隔,字符串比较两端必须有空格,用-eq代替=
  • [[ ]]:可以用逻辑判断&& ||和通配,两端需要空隔,字符串比较两端必须有空格,可以用=
  • (()):只可以判断整数,括号和符号两端有不有空格都行,可以用=
  • 数值判断用==字符串判断用=,但是为了方便全用= =,
  • 变量得加“”

1、test

只能加参数,判断文件目录字符串通过返回值来看是否正确,常见的参数有
-f:是否存在文件
-d:是否存在目录
-e:是否存在文件或者目录
-r:有可读权限(权限的判断仅限于对于正在使用的用户是否有这个权限)
-x:可执行权限
-w:可写权限
-s:文件的大小是否为0
-L:是否为链接文件
-nt:test 0 -nt 1 表示的是0文件是否比1文件新
-ot:0文件是否比1 文件旧
-z:判断变量、字符串是否为空
-n:判断是否不空

[root@all shell.test] ls
bianli.sh  dirname.sh   let.sh         panduan.sh   
[root@all shell.test] test -d ooo# 目录是否存在
[root@all shell.test] echo $?
1
[root@all shell.test] test -f panduan.sh 
[root@all shell.test] echo $?
0

  #判断字符串
[root@all shell.test] echo $name
dddd
[root@all shell.test] a=dddd
[root@all shell.test] echo $a
dddd
[root@all shell.test] test "$a" == "$name" #相等返回值为0
[root@all shell.test] echo $?
0
[root@all shell.test] test "aa" == "bb" # 不相等返回值为1 
[root@all shell.test] echo $?
1
# 判断数字
[root@all shell.test]# test 2 == 1 #不相等为1
[root@all shell.test]# echo $?
1

2、[ ]

用于文件、目录、字符串的判断,在括号里面要有空格,参数和test一样
-f:是否存在文件
-d:是否存在目录
-e:是否存在文件或者目录
-r:有可读权限(权限的判断仅限于对于正在使用的用户是否有这个权限)
-x:可执行权限
-w:可写权限
-s:文件的大小是否为0
-L:是否为链接文件
-nt:[ 0 -nt 1 ] 表示的是0文件是否比1文件新
-ot:0文件是否比1 文件旧
-z:判断变量、字符串是否为空
-n:判断是否不空

3、[[ ]]

也是判断文件、目录、字符串,也得有空格,可以存在通配,可以有逻辑判断
-f:是否存在文件
-d:是否存在目录
-e:是否存在文件或者目录
-r:有可读权限(权限的判断仅限于对于正在使用的用户是否有这个权限)
-x:可执行权限
-w:可写权限
-s:文件的大小是否为0
-L:是否为链接文件
-nt:[[ 0 -nt 1 ]] 表示的是0文件是否比1文件新
-ot:0文件是否比1 文件旧
-z:判断变量、字符串是否为空
-n:判断是否不空

4、(())

判断数字,且只能整数

[root@all shell.test] (( 1 == 1 ))
[root@all shell.test] echo $?
0

5、例题

1、判断字符串是否为空

[root@all shell.test] echo $name #变量不为空返回值因该是1
dddd
[root@all shell.test] test -z "$name"
[root@all shell.test] echo $?
1
[root@all shell.test] [ -z "$name" ]
[root@all shell.test] echo $?
1
[root@all shell.test] [[ -z "$name" ]]
[root@all shell.test] echo $?
1
[root@all shell.test] [[ -z "$b" ]] #变量为空,返回值为0
[root@all shell.test] echo $?
0

2、判断字符串是否相等
字符串比较两端等号要有空格,不然可能会逻辑错误

[root@all shell.test] echo $a
dddd
[root@all shell.test] echo $name
dddd
[root@all shell.test] [[ "$a" = "$name" ]]&& echo "yes" || echo "no"
yes
[root@all shell.test] test "$a" == "$name"
[root@all shell.test] echo $?
0
[root@all shell.test] [ "$a" = "$name" ]
[root@all shell.test] echo $?
0
[root@all shell.test] [[ "$a" = "$name" ]]
[root@all shell.test] echo $?
0

3、判断进程是否存在

[root@shell shell.test] cat process.sh 
ps -ef |grep httpd |grep -v grep >/dev/null 2>&1 && echo "okk" || echo "no"#第一种


num = `ps -ef |grep httpd |grep -v grep |wc -l`>/dev/null 2>&1#第二种
if [[ "$num" -ne 0 ]]
then 
    echo "fuwumeiqidong"
else
    echo "oooookk"
fi        


netstat -tunalp |grep 80 |wc -l# 第三种
port=`netstat -tunalp |grep -o 80`
if [[ $port -eq 80 ]]
then
        echo "服务正常..."
    else
            echo "mei启动..."
fi

killall -0 httpd >/dev/null 2>&1 && echo "ok" ||echo"no"#第四种

[root@shell shell.test] sh process.sh 
okk
oooookk
服务正常...
ok

4、判断用户是否存在

[root@shell shell.test] cat u_exist.sh 
read -p "please enter any name" name
id $name &>/dev/null && echo "exist" ||echo "no"
[root@shell shell.test] sh u_exist.sh 
please enter any namea
exist
[root@shell shell.test] sh u_exist.sh 
please enter any nameb
no

6、整数二元比较的操作

  • 比较符号两端要有空格
  • 在[ ]中可以使用= !=,但是不可以>
  • 在[[ ]]中尽量不要用-gt
    在这里插入图片描述

六、逻辑操作符

在这里插入图片描述

Guess you like

Origin blog.csdn.net/qq_46495338/article/details/114295105