Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。
Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。
声明变量:export name="value"
declare -i ab
声明整数型变量
""
:包含的变量会被解释
''
:包含的变量会当做字符串解释
``
:反引号中的内容会作为系统命令,并执行其内容,可以替换输出一个变量
declare
命令用来声明shell变量:
参数说明:
- +/- "-“可用来指定变量的属性,”+"则是取消变量所设的属性。
- -f 仅显示函数。
- r 将变量设置为只读。
- x 指定的变量会成为环境变量,可供shell以外的程序来使用。
- i [设置值]可以是数值,字符串或运算式。
# declare -i ef //声明整数型变量 # ef=1 //变量赋值(整数值) # echo $ef //显示变量内容 # declare +i ef //取消变量属性 # declare -r ab //设置变量为只读 # unset variable_name //删除变量
#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell。
变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界
string="abcd" echo ${#string} #输出 4
bash支持一维数组(不支持多维数组),并且没有限定数组的大小。
类似于 C 语言,数组元素的下标由 0 开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于 0。
在 Shell 中,用括号来表示数组,数组元素用"空格"符号分割开。定义数组的一般形式为:
数组名=(值1 值2 ... 值n)
例如:
array_name=(value0 value1 value2 value3)
或者
array_name=( value0 value1 value2 value3 )
还可以单独定义数组的各个分量:
array_name[0]=value0 array_name[1]=value1 array_name[n]=valuen
可以不使用连续的下标,而且下标的范围没有限制。
读取数组元素值的一般格式是:
${数组名[下标]}
例如:
valuen=${array_name[n]}
使用 @ 符号可以获取数组中的所有元素,例如:
echo ${array_name[@]}
获取数组长度的方法与获取字符串长度的方法相同,例如:
# 取得数组元素的个数 length=${#array_name[@]} # 或者 length=${#array_name[*]} # 取得数组单个元素的长度 lengthn=${#array_name[n]}
多行注释还可以使用以下格式:
:<<EOF 注释内容... 注释内容... 注释内容... EOF
EOF 也可以使用其他符号:
:<<' 注释内容... 注释内容... 注释内容... ' :<<! 注释内容... 注释内容... 注释内容... !
$1,$2,…:对应调用第1,第2等参数 $0:命令本身 $*:以一个单字符串显示所有向脚本传递的参数。如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。 $@:与$*相同,但是使用时加引号,并在引号中返回每个参数。如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。 $#:传递给脚本的参数的个数 $?:显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
$*
与$@
区别:
#!/bin/bash val=`expr 2 + 2` echo "两数之和为 : $val"
两点注意:
[root@master ~]# echo "today is `date` " today is 2022年 02月 05日 星期六 12:41:11 CST
[root@master ~]# wc -l mysql.sh 17 mysql.sh [root@master ~]# wc -l mysql.sh |cut -d' ' -f1 17 [root@master ~]# cat linecount.sh #!/bin/bash linecount="$(wc -l $1|cut -d' ' -f1)" echo "This file have ${linecount} lines"
[root@master ~]# cat /etc/passwd|head -10|tail -1 operator:x:11:0:operator:/root:/sbin/nologin #用户名:密码占位符:uid:gid:用户描述信息:家目录:登录指定shell [root@master ~]# cat /etc/passwd|head -10|tail -1|cut -d: -f3 11 [root@master shell]# cat id_sum.sh #!/bin/bash userid1=$(cat /etc/passwd|head -10|tail -1|cut -d: -f3) userid2=$(cat /etc/passwd|head -10|tail -1|cut -d: -f3) userid_sum=$[$userid1 + $userid2] echo $userid_sum
[root@master shell]# cat blank_count.sh #!/bin/bash blank1=$(grep "^$" $1 | wc -l) blank2=$(grep "^$" $1 | wc -l) allblank=$[$blank1 + $blank2] echo "The sum space line: $allblank" [root@master shell]# bash blank_count.sh /etc/httpd/conf/httpd.conf.bak ~/mysql.sh The sum space line: 74
-gt
:大于(greater than)
-ge
:大于等于
-eq
:等于
-ne
:不等于
-lt
:小于(less than)
-le
:小于等于
[root@master shell]# cat diff.sh #!/bin/bash read -p "请输入两个正整数" num1 num2 if [ $num1 -gt $num2 ];then echo "$num1 > $num2" elif [ $num1 -lt $num2 ];then echo "$num1 < $num2" else echo "$num1 = $num2" fi [root@master shell]# bash diff.sh 请输入两个正整数2 4 2 < 4
简单的存在性测试: -e FILE :文件存在性测试,存在为真,否则为假 存在性及类型测试: -b FLIE:是否存在且为块设备文件; -c FILE:是否存在且为字符设备文件; -d FILE:是否存在且为目录文件; -f FILE:是否存在且为普通文件; -h FILE 或 -L FILE : 存在且为符号链接文件; -p FIEL :是否存在且为命名管道文件; -S FILE:是否存在且为套接文件; 文件权限测试: -r FILE:是否存在且可读 -w FILE:是否存在且可写 -x FILE:是否存在可执行 文件特殊权限测试: -g FILE:是否存在且拥有sgid权限; -u FILE:是否存在且拥有suid权限; -k FILE:是否存在且拥有sticky权限; 文件大小测试: -s FILE:是否存在且非空 文件是否打开: - fd:fd表示文件描述符是否已经打开且与某终端相关 -N FILE:文件自动上一次读取之后是否被修改过; -O FILE:当前用户是否为文件的属主; -G FILE:当前有效用户是否为文件数组; 双目测试: FILE1 -ef FILE2 :FILE1与FILE2是否指向同一个设备上的相同inode FILE1 -nt FILE2:FILE1是否新于FILE2 FILE1 -ot FILE2:FILE1是否旧于FILE2
file="/var/www/runoob/test.sh" if [ -r $file ] then echo "文件可读" else echo "文件不可读" fi if [ -w $file ] then echo "文件可写" else echo "文件不可写" fi if [ -x $file ] then echo "文件可执行" else echo "文件不可执行" fi if [ -f $file ] then echo "文件为普通文件" else echo "文件为特殊文件" fi if [ -d $file ] then echo "文件是个目录" else echo "文件不是个目录" fi if [ -s $file ] then echo "文件不为空" else echo "文件为空" fi if [ -e $file ] then echo "文件存在" else echo "文件不存在" fi
逻辑运算符: &&代表的意思是当前一个命令执行成功时会继续执行后续的命令,当前一个命令执行失败的时候不会执行后续的命令 ||代表的意思是当前一个命令执行成功时不会继续执行后续的命令,当前一个命令执行失败的时候会执行后续的命令 第一种方式: COMMAND1 && COMMAND2 COMMAND1 || COMMAND2 ! COMMAND 第二种方式: EXPRESSION1 -a EXPRESSION2 EXPRESSION1 -o EXPRESSION2 ! EXPRESSION Note:必须使用测试命令进行
printf “%-10s %-8s %-4s**\n**” 姓名 性别 体重kg
printf “%-10s %-8s %-4.2f**\n**” 郭靖 男 66.1234
printf “%-10s %-8s %-4.2f**\n**” 杨过 男 48.6543
printf “%-10s %-8s %-4.2f**\n**” 郭芙 女 47.9876
执行脚本,输出结果如下所示:
姓名 性别 体重kg 郭靖 男 66.12 杨过 男 48.65 郭芙 女 47.99
%s %c %d %f 都是格式替代符,%s 输出一个字符串,%d 整型输出,%c 输出一个字符,%f 输出实数,以小数形式输出。
%-10s 指一个宽度为 10 个字符(- 表示左对齐,没有则表示右对齐),任何字符都会被显示在 10 个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。
%-4.2f 指格式化为小数,其中 .2 指保留2位小数。
if 判断条件;then 条件为真的分支代码 elif 判断条件;then 条件为真的分支代码 else 条件为假的分支代码 fi
[root@master shell]# cat user.sh #!/bin/bash if [ $# -lt 1 ];then echo "at least one argument" exit 1 fi if id $1 &> /dev/null;then echo "$1 exists" exit 0 else useradd $1 [ $? -eq 0 ] && echo "$1"|passwd --stdin $1 &>/dev/null echo "user $1 have been created" fi
[root@master shell]# ps -ef |grep -c mysql 1 [root@master shell]# ps -ef|grep mysql root 2818 1741 0 19:46 pts/1 00:00:00 grep --color=auto mysql if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "false"; fi
语法:
for var in item1 item2 ... itemN do command1 command2 ... commandN done
写成一行:
for var in item1 item2 ... itemN; do command1; command2… done;
for loop in 1 2 3 4 5 do echo "The value is: $loop" done 输出结果: The value is: 1 The value is: 2 The value is: 3 The value is: 4 The value is: 5 ---------------------- #!/bin/bash for str in This is a string do echo $str done 输出结果: This is a string
语法:
while condition do command done
实例:
#!/bin/bash int=1 while(( $int<=5 )) do echo $int let "int++" done
let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。
while循环可用于读取键盘信息:
echo '按下 <CTRL-D> 退出' echo -n '输入你最喜欢的语言: ' while read FILM do echo "$FILM 是最好的语言!" done
无限循环语法格式:
while : do command done
或者
while true do command done
或者
for (( ; ; ))
until 循环执行一系列命令直至条件为 true 时停止。
until 循环与 while 循环在处理方式上刚好相反。
一般 while 循环优于 until 循环,但在某些时候—也只是极少数情况下,until 循环更加有用。
until 语法格式:
until condition do command done
condition 一般为条件表达式,如果返回值为 false,则继续执行循环体内的语句,否则跳出循环。
以下实例我们使用 until 命令来输出 0 ~ 9 的数字:
#!/bin/bash a=0 until [ ! $a -lt 10 ] do echo $a a=`expr $a + 1` done
case … esac 为多选择语句,与其他语言中的 switch … case 语句类似,是一种多分支选择结构,每个 case 分支用右圆括号开始,用两个分号 ;; 表示 break,即执行结束,跳出整个 case … esac 语句,esac(就是 case 反过来)作为结束标记。
可以用 case 语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。
case … esac 语法格式如下:
case 值 in 模式1) command1 command2 ... commandN ;; 模式2) command1 command2 ... commandN ;; esac
实例:
echo '输入 1 到 4 之间的数字:' echo '你输入的数字为:' read aNum case $aNum in 1) echo '你选择了 1' ;; 2) echo '你选择了 2' ;; 3) echo '你选择了 3' ;; 4) echo '你选择了 4' ;; *) echo '你没有输入 1 到 4 之间的数字' ;; esac
break命令允许跳出所有循环(终止执行后面的所有循环)。
下面的例子中,脚本进入死循环直至用户输入数字大于5。
#!/bin/bash while : do echo -n "输入 1 到 5 之间的数字:" read aNum case $aNum in 1|2|3|4|5) echo "你输入的数字为 $aNum!" ;; *) echo "你输入的数字不是 1 到 5 之间的! 游戏结束" break ;; esac done
continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。
#!/bin/bash while : do echo -n "输入 1 到 5 之间的数字: " read aNum case $aNum in 1|2|3|4|5) echo "你输入的数字为 $aNum!" ;; *) echo "你输入的数字不是 1 到 5 之间的!" continue echo "游戏结束" ;; esac done
demoFun(){ echo "这是我的第一个 shell 函数!" } echo "-----函数开始执行-----" demoFun echo "-----函数执行完毕-----"