Hom's Blog


Shell中比较判断,控制,循环和函数

这里暂时讨论只针对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 
}


◆ 本文地址: http://platinhom.github.io/2015/06/14/shell-function-for-if/, 转载请注明 ◆

前一篇: Amber输入结构的预处理
后一篇: Shell变量,数组,运算及操作


Contact: Hom / 已阅读()
Source 类别: Coding  标签: Bash  Shell  Key