美文网首页
Linux shell 中一些符号$() ` `,${},$[]

Linux shell 中一些符号$() ` `,${},$[]

作者: danria | 来源:发表于2019-08-21 14:38 被阅读0次

    Shell中经常遇到一些符号容易混淆,今天一起总结学习下加深理解。

    1. $()``

    $()`` (反引号) 都是用来做命令替换用的。
    我们直接看例子:

    => echo 5加4等于:$(expr 5 + 4)
    5加4等于:9
    => echo 5加4等于:`expr 5 + 4`
    5加4等于:9
    

    在操作上,这两者都是达到相同的效果,但是建议使用$(),理由如下:
    在多层次的复合替换中,`` 必须要转义处理(反斜线),而$()比较直观。如下例子(只是为了说明多层次命令,不用介意具体运算):

    => echo 5加4加1等于:$(expr $(expr 5 + 4 ) + 1)
    5加4加1等于:10
    => echo 5加4加1等于:`expr \`expr 5 + 4\` + 1`
    5加4加1等于:10
    
    2. ${} :变量替换

    ${}用于变量替换。一般情况下,$var${var} 结果差不多。但是用 ${}会精确的界定变量名称的范围。例子:

    => file="test";echo $file_txt
    #空值,因为没有定义file_txt
    => file="test";echo ${file}_txt
    test_txt
    

    ${}的一些其他功能:

    1)${}信息提取

    主要有以下四种, 此部分内容参考学习(Linux shell 之 提取文件名和目录名的一些方法):
    我们以var=/home/test/dir1/dir2/V3_L01_99_2.fq.gz为例说明
    A. ${var##*.}:该命令的作用是去掉变量var从左边算起的最后一个'.'字符及其左边的内容,返回从左边算起的最后一个'.'(不含该字符)的右边的内容。结果如下:

    => var=/home/test/dir1/dir2/V3_L01_99_2.fq.gz
    => echo ${var##*.}
    gz
    

    因此使用该命令,可以提取出我们需要的文件后缀。

    B、${var#*.}: 该命令的作用是去掉变量var从左边算起的第一个'.'字符及其左边的内容,返回从左边算起第一个'.'(不含该字符)的右边部分的内容。例子结果如下:

    => var=/home/test/dir1/dir2/V3_L01_99_2.fq.gz
    => echo ${var#*.}
    fq.gz
    

    使用该命令,可以提取出文件的多个后缀。

    C、${var%/*}: 该命令的使用是去掉变量var从右边算起的第一个'/'字符及其右边的内容,返回从右边算起的第一个'/'(不含该字符)的左边的内容。例子结果如下:

    => var=/home/test/dir1/dir2/V3_L01_99_2.fq.gz
    => echo ${var%/*}
    /home/test/dir1/dir2
    

    从结果可看出,使用该命令,可以提取出需要的文件所在的目录。

    D、${var%%.*}: 该命令的使用是去掉变量var从右边算起的最后一个'.'字符及其右边的内容,返回从右边算起的最后一个'.'(不含该字符)的左边的内容。使用例子及结果如下:

    => var=/home/test/dir1/dir2/V3_L01_99_2.fq.gz
    => echo ${var%%.*}
    /home/test/dir1/dir2/V3_L01_99_2
    

    使用该命令,可以提取出需要的文件除去多个后缀后的路径与文件名。
    从这也可发现一些规律,即:
    #:表示从左边算起第一个
    ##:表示从左边算起最后一个
    %:表示从右边算起第一个
    %%:表示从右边算起最后一个

    当然上述操作的作用并不只是为了提取文件名或后缀,只是为了说明${}在信息提取上的应用;shell中文件名或后缀的提取可直接使用basename和dirname,还是以上述为例:
    => var=/home/test/dir1/dir2/V3_L01_99_2.fq.gz
    => echo $(basename $var)
    V3_L01_99_2.fq.gz
    => echo $(basename $var .fq.gz)
    V3_L01_99_2
    => echo $(dirname $var)
    /home/test/dir1/dir2
    
    2)${} substring 按字符位置、长度截取

    格式:${var:offset:length},取得字符串的子字符串
    直接看例子:

    var=/home/test/dir1/dir2/V3_L01_99_2.fq.gz
    echo ${var:0:5} #从头开始,提取最左边的 5 个字节,结果:/home
    echo ${var:5}   #从提取第 5 个字节右边到结尾的字符,结果:/test/dir1/dir2/V3_L01_99_2.fq.gz
    echo ${var:5:5} #提取第 5 个字节右边的连续 5 个字节,结果;/test
    echo ${#var}    #计算出字符串的长度,结果:38
    echo ${var: -5} #注意区分,中间有空格,提取最后五个字符,结果:fq.gz
    echo ${var:-5}  #结果:/home/test/dir1/dir2/V3_L01_99_2.fq.gz,为啥值等于$var,下面部分有解释
    echo ${var:(-5)} #注意上面三者的区分,结果:fq.gz
    
    
    3)${} 查找替换和删除

    此部分参考学习:bash字符串处理

    • 查找替换:
      ${var/pattern/replacement}:查找var变量存储的字符中第一次由pattern匹配到的内容,并替换为replacement;
      ${var//pattern/replacement}:查找var变量存储的字符中所有能够由pattern匹配到的内容,并替换为replacement;
      例子:
    => var=/home/test/dir1/dir2/V3_L01_99_2.fq.gz;echo ${var/dir/path}
    /home/test/path1/dir2/V3_L01_99_2.fq.gz
    => var=/home/test/dir1/dir2/V3_L01_99_2.fq.gz;echo ${var//dir/path}
    /home/test/path1/path2/V3_L01_99_2.fq.gz
    
    • 查找删除:

    ${var/pattern}:查找var变量存储的字符中第一次由pattern匹配到的内容,并删除;
    ${var//pattern}:查找var变量存储的字符中所有能够由pattern匹配到的内容,并删除;
    ${var/#pattern}:查找var变量存储的字符中最开始处能够由pattern匹配到的内容,并删除;
    ${var/%pattern}:查找var变量存储的字符中最后位置能够由pattern匹配到的内容,并删除;
    例子如下:

    => var=home/test/dir1/home2/dir2/home;echo ${var/home}
    /test/dir1/home2/dir2/home
    => var=home/test/dir1/home2/dir2/home;echo ${var//home}
    /test/dir1/2/dir2/
    => var=home/test/dir1/home2/dir2/home;echo ${var/#home}
    /test/dir1/home2/dir2/home
    => var=home/test/dir1/home2/dir2/home;echo ${var/%home}
    home/test/dir1/home2/dir2/
    
    4)${} 大小写替换

    ^替换为大写,^^统统替换为大写
    ,替换为小写,,,统统替换为小写

    var="home/test/dir1/dir2/V3_L01_99_2.fq.gz"
    echo ${var^} # Home/test/dir1/dir2/V3_L01_99_2.fq.gz
    echo ${var^^} # HOME/TEST/DIR1/DIR2/V3_L01_99_2.FQ.GZ
    echo ${var,} # home/test/dir1/dir2/V3_L01_99_2.fq.gz
    echo ${var,,} # home/test/dir1/dir2/v3_l01_99_2.fq.gz
    
    5)利用 ${} 还可针对不同的变量状态赋值(初始化、空值、非空值)

    本部分参考学习https://blog.csdn.net/x1269778817/article/details/46535729

    变量设定
    这也是上部分${var:-5} 结果为啥还是等于$var的原因。
    6) ${} 数组与关联数组

    shell中的数组与关联数组
    声明数组: declare -a array
    声明关联数组: declare -A MAP

    declare -a ARY     #声明数组
    declare -A MAP    #声明关联数组
    MAP=([a]=1 [b]=2 [cde]=3 [f]=F)     #关联数组MAP
    ARY=(a b cde f)                              #数组ARY
    
    echo ${ARY[2]}                               #数组ARY,从0开始,因此是第三个元素,cde
    echo ${#ARY[2]}                             #数组ARY,第三个元素的长度, 3
    echo ${ARY[@]}                             #数组所有元素, a b cde f
    echo ${ARY[*]}                                #数组所有元素, a b cde f
    echo ${#ARY[@]}                            #数组大小, 4
    echo ${ARY[@]:0:2}                        #数组从头开始前两个元素,a b
    echo ${ARY[@]: -2:2}                      #注意-2前面有空格,原因上面讲过,从最后一个元素-1开始向左数2个元素,cde f
    echo ${MAP[@]}                              #关联数组所有值,1 3 2 F
    echo ${#MAP[@]}                           #关联数组大小,4
    echo ${MAP[cde]}                           #关联数组cde的值,3
    echo ${!MAP[@]}                             #返回索引,a cde b f
    
    
    3. $[]$(())

    进行数学运算。支持+ - * / %:分别为 “加、减、乘、除、求余",如下:

    a=10;b=8;c=5;
    echo $a + $b          #输出:10 + 8
    echo $(( a + b*c))    #输出:50
    echo $(((a*b)/c))      #输出:16
    
    #在 $(( )) 中的变量名称,其前面可以加 $ 符号,也可以不用,如:
    
    echo $(( $a + $b * $c)) # 输出也是 50
    

    $[]$(()) 的过去形式,现在已经不建议使用

    4. []

    即为test命令的另一种形式。

    但要注意:

    1).必须在左括号的右侧和右括号的左侧各加一个空格,否则会报错。

    2).test命令使用标准的数学比较符号来表示字符串的比较,而用文本符号来表示数值的比较。

    3).字符比较的大于符号或小于符号必须要转义,否则会被理解成重定向。

    4). []中的逻辑与和逻辑或使用-a 和-o 表示
    例子:

    num=10
    str1=abc
    #字符串
    if [ $str1 = "abc" ];then
      echo "this is $str1"
    fi
    # 输出:this is abc
    # 数字
    if [ $num -gt 1 -a $num -lt 20 ];then
      echo "this is $num"
    fi
    # 输出:this is 10
    if [ $num -gt 1 ] && [ $num -lt 20 ];then
      echo "this is $num"
    fi
    # 输出:this is 10
    

    []条件判断的一些总结,此部分参考来源全网最全的 bash 速查表 ;

    statement1 && statement2  # and 操作符
    statement1 || statement2  # or 操作符
    
    exp1 -a exp2              # exp1 和 exp2 同时为真时返回真(POSIX XSI扩展)
    exp1 -o exp2              # exp1 和 exp2 有一个为真就返回真(POSIX XSI扩展)
    ( expression )            # 如果 expression 为真时返回真,输入注意括号前反斜杆
    ! expression              # 如果 expression 为假那返回真
    
    str1 = str2               # 判断字符串相等,如 [ "$x" = "$y" ] && echo yes
    str1 != str2              # 判断字符串不等,如 [ "$x" != "$y" ] && echo yes
    str1 < str2               # 字符串小于,如 [ "$x" \< "$y" ] && echo yes
    str2 > str2               # 字符串大于,注意 < 或 > 是字面量,输入时要加反斜杆
    -n str1                   # 判断字符串不为空(长度大于零)
    -z str1                   # 判断字符串为空(长度等于零)
    
    -a file                   # 判断文件存在,如 [ -a /tmp/abc ] && echo "exists"
    -d file                   # 判断文件存在,且该文件是一个目录
    -e file                   # 判断文件存在,和 -a 等价
    -f file                   # 判断文件存在,且该文件是一个普通文件(非目录等)
    -r file                   # 判断文件存在,且可读
    -s file                   # 判断文件存在,且尺寸大于0
    -w file                   # 判断文件存在,且可写
    -x file                   # 判断文件存在,且执行
    -N file                   # 文件上次修改过后还没有读取过
    -O file                   # 文件存在且属于当前用户
    -G file                   # 文件存在且匹配你的用户组
    file1 -nt file2           # 文件1 比 文件2 新
    file1 -ot file2           # 文件1 比 文件2 旧
    
    num1 -eq num2             # 数字判断:num1 == num2
    num1 -ne num2             # 数字判断:num1 != num2
    num1 -lt num2             # 数字判断:num1 < num2
    num1 -le num2             # 数字判断:num1 <= num2
    num1 -gt num2             # 数字判断:num1 > num2
    num1 -ge num2             # 数字判断:num1 >= num2
    
    5. (())[[]]

    (())[[]]分别是针对数学比较表达式字符串表达式的加强版。
    可参考:Bash test and comparison functions

    1. [[ ]] 结构比[ ]结构更加通用
    2. [[ ]]支持字符串的模式匹配,使用=~操作符时甚至支持shell的正则表达式。
      继续上面例子:
    num=10
    str1=abc
    
    if [[ $num -gt 1 && $num -lt 20 ]];then
      echo "this is $num"
    fi
    # 输出:this is 10,注意写成[ $num -gt 1 && $num -lt 20 ]会出错;
    if [[ $str1 =~ ab ]];then
      echo "this is $str1"
    fi
    # 输出:this is abc
    

    (( ))相比(),不需要再将表达式里面的大小于符号转义,除了可以使用标准的数学运算符外,还增加了自增自减等符号;如

    for ((i = 0; i < 10; i++)); do echo $i; done
    # 输出0-9的数
    

    其他功能,如{n..m} 代表n-m之间的数字,如{0..4}$(seq 0 4)表示相同意思。/{,s}bin/表示/bin/和/sbin/,ab{c,d,e}表示abc、abd、abe,如实现文件的快速备份:cp run.sh{,.bak}。
    当然随时可查看bash 速查表

    有参考Shell 参数扩展及各类括号在 Shell 编程中的应用

    相关文章

      网友评论

          本文标题:Linux shell 中一些符号$() ` `,${},$[]

          本文链接:https://www.haomeiwen.com/subject/dwxdsctx.html