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命令会把从管道中获得的输入拆分,逐个作为下一个命令的输入。 

  • 相关阅读:
    poj 3080 kmp+暴力
    org.apache.spark.rpc.RpcTimeout$$anonfun$1.applyOrElse
    log4j:WARN No appenders could be found for logger
    HBase2.0.5 WordCount
    Eclipse连接HBase 报错:org.apache.hadoop.hbase.PleaseHoldException: Master is initializing
    Eclipse Oxygen.2 Release (4.7.2)添加JUnit
    hiveserver2启动成功但无法通过beeline连接
    vi从当前行删除到最后一行
    Hive SemanticException
    Hive启动失败
  • 原文地址:https://www.cnblogs.com/xinchrome/p/5062017.html
Copyright © 2011-2022 走看看