zoukankan      html  css  js  c++  java
  • Bourne Shell:控制语句、条件判断、文本处理、常用命令

        条件判断是一个程序获得智能的基础,而Bourne Shell脚本则通过命令 [ 来模拟大多数编程语言中的条件表达式。

        shell中支持的控制结构有:

    (1) if then else fi

    (2) for in do done

    (3) while do done

        这些关键字可以引导程序检查状态码 $?,从而实现控制。下面讲解这个命令如何模拟条件表达式。

    文件/目录判断
    [ -b FILE ] 如果 FILE 存在且是一个块特殊文件则为真。
    [ -c FILE ] 如果 FILE 存在且是一个字特殊文件则为真。
    [ -d DIR ] 如果 FILE 存在且是一个目录则为真。
    [ -e FILE ] 如果 FILE 存在则为真。
    [ -f FILE ] 如果 FILE 存在且是一个普通文件则为真。
    [ -g FILE ] 如果 FILE 存在且已经设置了SGID则为真。
    [ -k FILE ] 如果 FILE 存在且已经设置了粘制位则为真。
    [ -p FILE ] 如果 FILE 存在且是一个名字管道(F如果O)则为真。
    [ -r FILE ] 如果 FILE 存在且是可读的则为真。
    [ -s FILE ] 如果 FILE 存在且大小不为0则为真。
    [ -t FD ] 如果文件描述符 FD 打开且指向一个终端则为真。
    [ -u FILE ] 如果 FILE 存在且设置了SUID (set user ID)则为真。
    [ -w FILE ] 如果 FILE存在且是可写的则为真。
    [ -x FILE ] 如果 FILE 存在且是可执行的则为真。
    [ -O FILE ] 如果 FILE 存在且属有效用户ID则为真。
    [ -G FILE ] 如果 FILE 存在且属有效用户组则为真。
    [ -L FILE ] 如果 FILE 存在且是一个符号连接则为真。
    [ -N FILE ] 如果 FILE 存在 and has been mod如果ied since it was last read则为真。
    [ -S FILE ] 如果 FILE 存在且是一个套接字则为真。
    [ FILE1 -nt FILE2 ] 如果 FILE1 has been changed more recently than FILE2, or 如果 FILE1 exists and FILE2 does not则为真。
    [ FILE1 -ot FILE2 ] 如果 FILE1 比 FILE2 要老, 或者 FILE2 存在且 FILE1 不存在则为真。
    [ FILE1 -ef FILE2 ] 如果 FILE1 和 FILE2 指向相同的设备和节点号则为真。

    字符串判断
    [ -z STRING ] 如果STRING的长度为零则为真 ,即判断是否为空,空即是真;
    [ -n STRING ] 如果STRING的长度非零则为真 ,即判断是否为非空,非空即是真;
    [ STRING1 = STRING2 ] 如果两个字符串相同则为真 ;
    [ STRING1 != STRING2 ] 如果字符串不相同则为真 ;
    [ STRING1 ]  如果字符串不为空则为真,与-n类似

    数值判断
    INT1 -eq INT2 INT1和INT2两数相等为真 ,=
    INT1 -ne INT2 INT1和INT2两数不等为真 ,<>
    INT1 -gt INT2 INT1大于INT1为真 ,>
    INT1 -ge INT2 INT1大于等于INT2为真,>=
    INT1 -lt INT2 INT1小于INT2为真 ,<
    INT1 -le INT2 INT1小于等于INT2为真,<=

    总之,“=”用于比较字符串;“-eq”用于比较整型数

    复杂逻辑判断
    -a 与
    -o 或
    ! 非

    1、如果a>b且a<c
    if (( a > b )) && (( a < c ))
    if [[ $a > $b ]] && [[ $a < $c ]]
    if [ $a -gt $b -a $a -lt $c ]

    2、如果a>b或a<c
    if (( a > b )) || (( a < c ))
    if [[ $a > $b ]] || [[ $a < $c ]]
    if [ $a -gt $b -o $a -lt $c ]

    "||"和"&&"在SHELL里可以用,第一个可以写成if [ a>b && a ]

     双括号和双中括号的含义见下文中对各种括号的解释。

    Shell中的括号(), (()), [], [[]]

    1、单小括号 ()
    ①命令组。括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用。括号中多个命令之间用分号隔开,最后一个命令可以没有分号,各命令和括号之间不必有空格。
    ②命令替换。等同于`cmd`,shell扫描一遍命令行,发现了$(cmd)结构,便将$(cmd)中的cmd执行一次,得到其标准输出,再将此输出放到原来命令。注意花括号${}也可以被看做命令替换,但是两者有所区别,花括号内是定义好的变量,而不是shell命令。
    ③用于初始化数组。如:array=(a b c d)

    2、双小括号 (( ))
    ①整数扩展。这种扩展计算是整数型的计算,不支持浮点型。((exp))结构扩展并计算一个算术表达式的值,如果表达式的结果为0,那么返回的退出状态码为1,或者 是"假",而一个非零值的表达式所返回的退出状态码将为0,或者是"真"。
    ②只要括号中的运算符、表达式符合C语言运算规则,都可用在$((exp))中。作不同进位(如二进制、八进制、十六进制)运算时,输出结果全都自动转化成了十进制。如:echo $((16#5f)) 结果为95 (16进位转十进制)。单纯用 (( )) 也可重定义变量值,比如 a=5; ((a++)) 可将 $a 重定义为6。双括号中的变量可以不使用$符号前缀。括号内支持多个表达式用逗号分开。
    ③甚至可以替代循环结构,只要括号中的表达式符合C语言运算规则。比如可以直接使用for((i=0;i<5;i++)), 如果不使用双括号, 则为for i in `seq 0 4`或者for i in {0..4}。再如可以直接使用if (($i<5)), 如果不使用双括号, 则为if [ $i -lt 5 ]。

    3、单中括号 []
    ①标准命令 [ 和 test 是具有相同作用,区别在于 [ 命令的最后一个参数是 "]" 。
    ②在正则表达式中用于表示字符范围。作为test用途的中括号内不能使用正则。
    ④在一个array 结构的上下文中,中括号用来引用数组中每个元素的编号。

    4、双中括号[[ ]]
    ①[[是 bash 程序语言的关键字,并不是一个命令。[[ ]] 结构比[ ]结构更加通用,不过注意[[ 依然要和中括号内的内容用空格隔开。
    ②支持字符串的模式匹配,使用=~操作符时支持正则表达式,使用==操作符时则支持通配符,字符串比较时可以把右边的作为一个模式,而不仅仅是一个字符串,比如[[ hello == hell? ]],结果为真。
    ③使用[[ ... ]]条件判断结构,而不是[ ... ],能够防止脚本中的许多逻辑错误。比如,&&、||、<和> 操作符能够正常存在于[[ ]]条件判断结构中,但是如果出现在[ ]结构中的话,会报错,原因是 [ 命令不能解释&&的含义。比如可以直接使用if [[ $a != 1 && $a != 2 ]], 如果使用单括号, 则为if [ $a -ne 1] && [ $a != 2 ]或者if [ $a -ne 1 -a $a != 2 ]。
    ④bash把双中括号中的表达式看作一个单独的元素,并返回一个退出状态码。

    语法提醒:shell有时靠命令来模拟运算。例如四则运算可以借助:let, expr 等命令完成。如对变量 x 加 1 可以写作:let "x = $x + 1" 或者 x=`expr $x + 1‘ 。如果参数有空格,一定要用引号括起来才不会出错。空格在shell中是有意义的。

    PS:注意shell中,所有的输入都是字符串类型(当然任何语言都是如此,只是shell支持的类型解释和转换比较少),其中美元符$ 反引号` 反斜线 都被sh进程或者bash进程解释成字符串替换或命令替换,也就是用特定的输出字符串替换原命令,然后再继续执行新的命令。

    调试:

    查看shell脚本的执行过程
    在执行的时候,通过下面的方式:
    #sh -x test.sh

    获取命令行参数:

        注意 $ 是一个被解释成命令替换的符号,和反引号有类似之处。

    $# 是传给脚本的单词个数
    $0 是脚本本身的名字
    $1 是传递给该shell脚本的第一个单词
    $2 是传递给该shell脚本的第二个单词
    $@ 是传给脚本的所有单词组成的列表数据结构
    $* 将被替换成一个被包括在引号内的字符串,以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9个
    $$ 是脚本运行的当前进程ID号
    $? 是显示最后命令的退出状态,0表示没有错误,其他表示有错误

    shell文本处理

        重点掌握三个命令:find, grep, sed, awk,也就实现了对文本的增(插入)、删、改(替换)、查

    1、find命令用于查找文件,如:

    xin$ sudo find / -type f -size +1G

    -name   filename             #查找名为filename的文件

    用于查找磁盘上大于1G的文件。

    2、grep命令用于查找文本,格式为:

    grep <pattern> <filename>

    3、sed命令用于编辑文本文件,最基本的命令当然是插入和删除,格式为: 

    sed [options] 'command' file(s) 注意用单引号而不是双引号, $ ` 等才不会被shell解释成字符串替换标志,而会直接把字面值转交给sed解释。

    options:

    -i :直接修改读取的文件内容,而不是将程序的结果输出到终端。

    command:

    格式 [n1,[n2]] function 其中 n1 和 n2 表示目标文本的首行行号和尾行行号

    function:

    a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)
    c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行
    d :删除,因为是删除啊,所以 d 后面通常不接任何字符串
    i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行)
    p :列印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行
    s :替换,可以直接进行取代的工作,通常这个 s 的动作可以搭配正规表示法,例如 1,20s/old/new/g

    $:代表最后一行

    示例:

    替换:

    Linux格式为:sed -i "s/192.168.0.2/192.168.0.3/g" *.rptdesign 

    Mac格式为:sed -i "" "s/192.168.0.2/192.168.0.3/g" *.rptdesign 相当于需要一个备份文件

    删除:

    sed -i "" '/^abc/d' ~/tmp/tmp.txt

    插入:

    sed -i "" '/192/a
    abc
    ' ~/tmp/tmp.txt

    管道

    示例: $ find .  | xargs svn add --force *.* 

    xargs命令会把从管道中获得的输入拆分,逐个作为下一个命令的输入。 

  • 相关阅读:
    HTTP断点续传 规格严格
    Java Shutdown 规格严格
    linux 命令源码 规格严格
    JTable调整列宽 规格严格
    linux 多CPU 规格严格
    Hello can not find git path 规格严格
    Kill 规格严格
    拜拜牛人 规格严格
    Swing 规格严格
    Debugging hangs in JVM (on AIX but methodology applicable to other platforms) 规格严格
  • 原文地址:https://www.cnblogs.com/xinchrome/p/5062017.html
Copyright © 2011-2022 走看看