Shell脚本基础概念
环境变量
set
printenv
env
这三个函数可以用来查看已经设置的环境变量,可以用${variable}来直接调用。
用户变量
允许自行定义和使用的变量。在Shell语言的一些基础用法及注意事项-Ⅰ 有提到。
用户自定义的变量在脚本整个生命周期里都是保持存在的,但shell脚本结束时会被删掉。
命令替换
shell脚本最有用的特性之一就是可以从命令输出中提取信息,并将其赋值给变量。把输出赋值给变量之后,就可以在脚本中随意使用。
两种方法把命令输出赋值给变量:
反引号字符(`)
$() 格式
方括号
算数运算
使用方括号可以简单的数学运算,并将运行结果赋值给某个变量。(只能进行整数运算)
var1=$[ 1 + 5 ]
echo ${var1}
var2=$[ ${var1} * 2 ]
echo ${var2}
[ $var -eq 0 ] 当$var 等于0时,返回真
[ $var -ne 0 ] 当$var 不等于0时,返回真
test命令
由于if-then语句 不能测试命令状态码之外的条件,所以shell提供了test命令用于帮助if-then语句测试其他条件,如 数值比较、字符串比较、文件比较等等。test命令的简写模式就是方括号[],使用方括号要注意方括号和内容之间要用空格间隔开,否则会报错。
数值比较
运算符 | 说明 |
---|---|
-eq | 检测两个数是否相等,相等返回 true。 |
-ne | 检测两个数是否不相等,不相等返回 true。 |
-gt | 检测左边的数是否大于右边的,如果是,则返回 true。 |
-lt | 检测左边的数是否小于右边的,如果是,则返回 true。 |
-ge | 检测左边的数是否大于等于右边的,如果是,则返回 true。 |
-le | 检测左边的数是否小于等于右边的,如果是,则返回 true。 |
value1=10
value2=15
#
if [ $value1 -gt 5 ]
then
echo "$value1 大于 5"
fi
############
if [ $value1 -eq $value2 ]
then
echo "$value1 和 $value2相等"
else
echo "$value1 和 $value2不等"
fi
注意:Bash Shell只能处理整数,处理浮点数会报错。
字符串比较
比较 | 描述 |
str1 = str2 | 检查str1是否和str2相同 |
str1 != str2 | 检查str1是否和str2不同 |
str1 < str2 | 检查str1是否比str2小 |
str1 > str2 | 检查str1是否比str2大 |
-n str1 | 检查str1的长度是否非0 |
-z str1 | 检查str1的长度是否为0 |
其中字符串比较大小有一些要注意的点:大于号、小于号必须转义,这里的比较和sort比较原理不同(ASCⅡ问题)。
在使用字符串比较大小时一定要注意、慎重
文件比较
文件比较时shell编程中最为强大、使用最多的比较形式。
比较 | 描述 |
-d file | 检查file是否存在并是一个目录 |
-e file | 检查file是否存在 |
-f file | 检查file是否存在并是一个文件 |
-r file | 检查file是否存在并可读 |
-s file | 检查file是否存在并非空 |
-w file | 检查file是否存在并可写 |
-x file | 检查file是否存在并可执行 |
-O file | 检查file是否存在并属当前用户所有 |
-G file | 检查file是否存在并且默认组与当前用户相同 |
file1 -nt file2 | 检查file1是否比file2新 |
file1 -ot file2 | 检查file1是否比file2旧 |
复合条件测试
if-then 允许使用布尔逻辑来组合测试。
- [ condition1 ] && [ condition2 ]
- [ condition1 ] || [ condition2 ]
#/home/bin
if [ -d $HOME ] && [ -w $HOME/testing ]
then
echo "file exists and can write"
else
echo "cannot write to file"
fi
双方括号
双方括号命令提供了针对字符串比较的高级用法,提供了匹配模式(pattern matching)(正则匹配)
结构化命令
if-then 语句
if command
then
commands
fi
####也可写成如下格式
if command; then
command
fi
bash shell 的if语句会运行if后面的那个命令。如果执行的退出状态码是0(命令运行成功),位于then部分的命令就会被执行。如果该命令的退出状态码是其他值,then部分的命令就不会被执行。
if-then-else 语句
if command
then
commands
else
commands
fi
当if语句中的命令返回退出状态码0时,then部分被执行;当if语句中的命令返回非零退出状态码时,else部分被执行。
嵌套 if
if command
then
commands
elif command
then
commands
else
commands
fi
test 命令
前面已经提到了test命令,提供了在if-then语句中测试不同条件的途径。
if [condition]
then
commands
fi
test命令可以判断三类条件:数值比较、字符串比较、文件比较。在上文已经提到了,这里不再赘述。
case 命令
如果需要连续使用if-then-elfi-then…else-fi 嵌套,可以尝试使用case命令
case variable in
pattern1 | pattern2) commands1;;
pannern3 | pattern4) commands2;;
pannern5) commands3;;
*) defaultcommands;;
esac
case命令会将指定的变量与不同模式经行比较。如果变量与模式是匹配的,那么shell会执行该模式指定的命令。可通过竖线操作符在一行中分割出多个模式。星号会捕获所有与已知模式不匹配的值。
for 命令
for var in list
do
commands
done
####也可写成如下格式
for var in list ; do
commands
done
这里需要注意如果list的内容如果复杂了(例如包括单引号),可能会出现问题。
解决办法是使用反斜杠转义、使用双引号把每个元素单独括起来。
涉及到的一个相关环境变量:内部字段分隔符(internal field separator )IFS。默认情况下IFS是空格、制表符、换行符。
while 命令
while test command
do
other commands
done
while命令只要测试命令的退出状态码是0,就会循环执行一次循环体内的命令。
until 命令
until test command
do
other commands
done
until命令只要测试命令的退出状态码是不是0,就会循环执行一次循环体内的命令。
控制循环
- break 退出循环
- continue 跳过本次循环
break 可以加参数,用于指定退出循环的层级
continue 可以加参数,用于指定继续执行那一层循环
&& ||
&& 表示前一条命令执行成功时,才执行后一条命令;
|| 表示上一条命令执行失败后,才执行下一条命令。
&&、|| 属于逻辑运算符,可以做简单的逻辑判断。
Shell 逐行读取文件的方法
方法1:while循环中执行效率最高,最常用的方法。
while read line
do
echo ${line}
done < filename
#这种方式在结束的时候需要执行文件,就好像是执行完的时候再把文件读进去一样。
方法2 : 管道法: cat $FILENAME | while read LINE
cat filename | while read line
do
echo ${line}
done
#当遇见管道的时候管道左边的命令的输出会作为管道右边命令的输入然后被输入出来。
方法3 for 循环。
for line in `cat filename`
do
echo ${line}
done
#这种方式是通过for循环的方式来读取文件的内容
注意:
在for循环读取文件操中,循环的变量是用IFS(内部字段分隔符)分隔的,默认的IFS是空格、制表符、换行符。所以for循环读取文件循环的每个元素不一定是一行的内容。
而while 循环读取文件操中,文件分割符是换行符。
所以一般针对“逐行读取文件”的操作建议使用前两种while的方法,如果要使用for循环,要注意输入文件是否有空格、制表符;或者提前修改环境变量$IFS.