这里暂时讨论只针对Bash及对应变体,csh等与bash差异较大,在此不讨论.
比较和判断
注意: 在判断中括号[]和内容之间,以及判断符(哪怕是=)的左右都要保留空格!否则没有判断功效,当作字符串.
- test,
[]与[[ ]],(()):test函数后面跟上表达式,表达测试,返回0/1.可以用echo $?追踪上一条命令返回结果,也可以使用&&前者对则运行,||前者错则运行.[ expr ]效果和test一样,注意expr和中括号间的空格.在if中最常用的形式.[[ expr ]]:模式匹配,功能更强大.可以结合&&和||进行进一步判断运算;<>在内部可以不转义;会进行元字符匹配(模式匹配); 变量甚至可以不需要$来调用;在[[和]]之间所有的字符都不会发生文件名扩展或者单词分割,但是会发生参数扩展和命令替换。(( expr )):一般数学运算,若用来作判断,非0时为真,为0为假.
test 3 -gt 4 && echo True || echo false
[ "abc" != "def" ];echo $?
test -d "$HOME" ;echo $?
[[ ( -d "$HOME" ) && ( -w "$HOME" ) ]] && echo "home is a writable directory"
[[ "abc def .d,x--" == a[abc]*\ ?d* ]]; echo $?
-
数值比较:
-eq等于,-ne不等于,-gt大于,-ge大于等于,-lt小于,-le小于等于.
如[ 3 -eq $mynum ],直接用数字 - 字符串比较:
-z空字符串;-n非空字符串: 使用-z或-n判断字符串变量时,必须要用”“把变量引起来。=或==字符串全等;!=字符串不等;>,<字符串大小比较(按字符比较),注意此时要\>,\<来使用防止误解为重定向符号.
如[ -z "$myvar" ],[ "$myvar" = "one two three" ].
一般加入双引号避免空格的干扰.
- 文件判断
- 一元判断符:
-e或-a文件或文件夹存在;-d文件夹;-f文件;-L或-h链接;-s非空文件;-w可写;-r可读;-x可执行;-b二进制文件;-c字符型文件;-u具suid; - 二元判断符:
f1 -nt f2:文件1比文件2新(或文件2不存在);f1 -ot f2:文件2比文件1新(或文件1不存在);f1 -ef f2测试file1是不是file2 的硬链接。
- 一元判断符:
- and-or-not:
!,一元操作符,比and和or优先.-o, 二元,or或-a,二元,and与.注意别和文件测试的-a file一元符搞混.\( \),可以改变运算优先级,要注意对括号进行转义!
再强调<>()是需要转义的!
更多可参考IBM-Linux技巧:Bash测试和比较函数.
变量与运算用法请参考Shell变量,数组,运算及操作
控制
Bash支持if判断和case选择语句.在但命令行也常用&&和||进行控制.
## if...fi
if [ expression ]
then
commands
elif [ expression ];then
commands
else
commands2
fi
## Case..esac
case $a in
1)
commands
;;
*)
commands
;;
esac
## && and ||
command && command1 || command2
if [ true ];then更常一句写完.- 判断条件expression和中括号之间要留有空格
[]判断条件可以用某个命令来替代,此时根据命令返回值0/1作判断,例如用test,grep.if test 1 -lt 2 ;then- case可以把
1) commands ;;写在一行. &&与||接在命令后,表示命令返回正常(0)时则执行后续&&后命令,否则执行||后的命令.
循环
Bash支持while/until do循环和for do循环
## while..do..done
while [ expression ] #可以true/false
do
commands
done
## until..do..done
until [ expression ] #可以true/false
do
commands
done
## for..do..done
for var in argument-list
do
commands
done
- 在
for do中,argument-list可以是”a b c”的字符串(如$*),可以是a b c的字符串列表(如$@), 可以是产生字符串的命令ls, 可以是$*所有参数,可以是通配符*等产生的结果, 或$(command),或$listvar. - for循环中常配合
seq start interval end产生数字串配合. for in的in部分甚至可以用*.txt来获取所有txt,但小心空格!- 打断循环:
break,continue
函数
使用function fname{}方法定义.功能比较弱:返回值只能是整数,没有实际形参的定义.
[function] fname[()]
{
echo $1 $2
statements;
[return int;]
}
fname p1 p2
- function关键词可省略,甚至()也可以省略.不建议省略.
- 返回值是0~255的整数.若不输入return语句,则返回最后一句的返回值.
- 可用
$?显示最后命令的退出状态,可以用于函数调用后的返回值的获取。一般地0表示没有错误,其他任何值表明有错误. 注意使用=获取的是输出(stdout)而非返回值! - 函数的参数使用shell脚本的参数传递的方法.
$n. n是对应1,2,3,就是获取对应的参数.$#获取参数个数.$@和$*获取所有参数,前者字符串化逐个来,后者所有参数再字符串化.$0函数本身
- 函数内部定义变量时使用
local var=value可以定义局部变量, 在函数内使用和改变变量将影响局部变量而非外部变量. - 自定义函数需要在执行前先定义,不能定义在文件末尾.可以写到sh文件后进行source,可以写到.bashrc里进行预加载.
- 系统在搜索命令时先搜可执行命令,随后再到自定义函数.
- 删除定义的函数用
unset .f function_name命令,需要.f指明函数.
例子
函数
# 批处理对后缀名为选项1的进行后面的指令.
function batchexec()
{
find . -type f -iname '*.'${1}'' -exec ${@:2} {} /; ;
}
# 所有sh文件进行775权限操作.
batchexec sh chmod 755
# 根据文件名后缀进行解压,case的运用.
function extract() {
if [ -f $1 ] ; then
case $1 in
*.tar.bz2) tar xjf $1 ;;
*.tar.gz) tar xzf $1 ;;
*.bz2) bunzip2 $1 ;;
*.rar) unrar e $1 ;;
*.gz) gunzip $1 ;;
*.tar) tar xf $1 ;;
*.tbz2) tar xjf $1 ;;
*.tgz) tar xzf $1 ;;
*.zip) unzip $1 ;;
*.Z) uncompress $1 ;;
*.7z) 7z x $1 ;;
*) echo "'$1' cannot be extracted via extract()" ;;
esac
else
echo "'$1' is not a valid file"
fi
}