• (转)shell变量及扩展


    1、shell变量

    shell变量赋值语句为”name=[value]“,等号两边不能有空格,可以给shell变量追加内容”name+=value“,取消shell变量的设置使用”unset name”,例子如下。

    $ var=1
    $ echo $var
    1
    $ var=123
    $ echo $var
    123
    $ var+=100
    $ echo $var
    123100
    $ var=a
    $ echo $var
    a
    $ var=abc
    $ echo $var
    abc
    $ var+=xxx
    $ echo $var
    abcxxx
    $ unset var
    $ echo $var

    2、shell扩展

    命令行被拆分成符号以后要进行扩展,扩展有多种方式,且有一定的顺序:大括号扩展,波浪号扩展、参数、变量和算术扩展以及命令替换(从左到右),单词拆分,以及文件名扩展,如果系统支持,则还有另外一种扩展,即进程替换,它与参数、变量和算术扩展以及命令替换是同时进行的。只有大括号扩展,单词扩展以及文件名扩展在扩展时能够改变单词的数目,其它的扩展都是单个单词扩展成单个单词,唯一例外的是对"$@""${array[@]}"的扩展,所有扩展完成后再进行引用去除。下面对这些shell扩展逐个介绍。

    3、大括号扩展

    大括号扩展是一种能够生成任意字符串的机制,基本形式为“prefix{var,var2,var3…}suffix”或者“prefix{x..y[..increment]}suffix”。大括号扩展的前缀prefix、后缀suffix是可选的,大括号内的内容为以逗号分隔的字符串或者一个序列表达式,从左到右进行扩展。对于字符串来说,它们以逗号分隔,如果只有一个字符串,在这个字符串的后面有无逗号的效果是不同的。对于序列表达式来说,x和y是一个整数或者单个字符,类型必须相同,后面的增量increment是个可选的整数值,默认为1或者-1,根据x和y的大小进行选择,当x和y为整数时,整数的前面可添加一个0,用以限定整数的宽度,高位不足时用0补齐,最终扩展为包括x和y的从较小值到较大值之间的一系列值。

    $ foo() { echo a{foo, bar}z; }
    $ foo
    afooz abarz
    $ foo() { echo a{01..10..2}z; }
    $ foo
    a01z a03z a05z a07z a09z

    格式正确的大括号扩展必须包含没有被引用的起始和结束大括号,还有至少一个未被引用的逗号或者序列表达式。大括号扩展在其它所有扩展之前进行,为了避免与参数扩展冲突,大括号扩展不会识别字符串中的“${”,为了防止被认为是大括号扩展的一部分,大括号和逗号可以使用反斜杠转义。

    4、波浪号扩展

    如果一个单词以未被引用的波浪号“~”开头,则其后的所有字符,直到第一个未被引用的斜杠(如果有的话),都被看作是波浪号前缀。如果波浪号前缀中的字符都没有被引用,则其中波浪号后面的所有字符就被当作一个可能存在的登录用户名,如果这个登录名是个空字符串,波浪号就被替换成shell特殊变量HOME的值,如果没有设置HOME,则替换成执行该命令的那个用户的主目录,否则,替换成其中指定的那个登录名的主目录。

    ~    扩展为"$HOME"
    ~/foo    扩展为"$HOME/foo"
    ~username/foo    扩展为用户username的主目录中的子目录foo

    在波浪号前缀中,可以有加号、减号。

    ~+    扩展为"$PWD"
    ~-    扩展为"$OLDPWD"

    在波浪号前缀中,还可以使用整数进行目录栈(对应的内建命令为pushd、popd、dirs)扩展。

    ~N    命令"dirs +N"显示的字符串
    ~+N    命令"dirs +N"显示的字符串
    ~-N    命令"dirs -N"显示的字符串

    5、参数(变量)扩展

    参数扩展使用美元符号“$”进行引导,参数一般放在一对未被引用的大括号内,基本格式为:

    ${parameter}

    使用了冒号“:”的几种情形:

    ${parameter:-word}    如果parameter没有设置或者为空,替换为word;否则替换为parameter的值。
    ${parameter:+word}    如果parameter没有设置或者为空,不进行任何替换;否则替换为word。
    ${parameter:=word}    如果parameter没有设置或者为空,把word赋值给parameter。最终替换为parameter的值。
    ${parameter:?word}    如果parameter没有设置或者为空,把word输出到stderr,否则替换为parameter的值。
    ${parameter:offset}    扩展为parameter中从offset开始的子字符串。
    ${parameter:offset:length}     扩展为parameter中从offset开始的长度不超过length的字符。

    使用了叹号“!”的几种情形(间接扩展):

    ${!prefix*}    扩展为变量名中含有prefix的一些变量。
    ${!prefix@}    扩展为变量名中含有prefix的一些变量。
    ${!name[*]}    如果name为数组,扩展为name的索引;否则结果为0。如果name未定义,结果为空。
    ${!name[@]}    如果name为数组,扩展为name的索引;否则结果为0。如果name未定义,结果为空。

    使用了井号“#”的几种情形:

    ${#parameter}    结果为parameter所包含的字符数。
    ${parameter#word}    word与parameter从最左边开始进行模式匹配,结果为从parameter最左边删除匹配到的最短字符串后剩下的内容。
    ${parameter##word}     word与parameter从最左边开始进行模式匹配,结果为从parameter最左边删除匹配到的最长字符串后剩下的内容。

    使用了百分号“%”的几种情形(与“#”相反):

    ${parameter%word}    word与parameter从最右边开始进行模式匹配,结果为从parameter最右边删除匹配到的最短字符串后剩下的内容。
    ${parameter%%word}     word与parameter从最右边开始进行模式匹配,结果为从parameter最右边删除匹配到的最长字符串后剩下的内容。

    字符串替换:

    ${parameter/pattern/string}    pattern为一种模式,把parameter中与之匹配的最长字符串用string替换。若pattern以#开头,只匹配parameter的开头;若pattern以%开头,只匹配parameter的结尾;若pattern以/开头,会替换所有匹配到的内容,否则只替换第一个匹配到的内容;若string为空,可省略pattern后面的/,表示删除匹配到的内容。

    字符大小写转换(pattern省略时表示可以匹配每个字符的?):

    ${parameter^pattern}    把parameter中与pattern匹配的第一个字符转为大写字母。
    ${parameter^^pattern}    把parameter中与pattern匹配的所有字符转为大写字母。
    ${parameter,pattern}    把parameter中与pattern匹配的第一个字符转为小写字母。
    ${parameter,,pattern}    把parameter中与pattern匹配的所有字符转为小写字母。

    6、算术扩展

    算术扩展可以完成一个真正的数学运算,格式为:

    $((expression))

    例如:

    $ foo=1
    $ var=$((foo+=10))
    $ echo $var
    11

    7、命令替换

    命令替换把命令执行的标准输出取代命令本身,格式为:

    $(command)
    `command`

    例如:

    $ uname -p
    x86_64
    $ foo=$(uname -p)
    $ echo $foo
    x86_64

    8、进程替换

    如果系统支持命名管道”fifo“或者能够以”/dev/fd“方式来命名打开的文件,那么也就支持进程替换,格式为:

    <(command)
    >(command)

    进程替换中的尖括号与左边的圆括号之间不能留有空格。执行命令时,其输入和输出与命名管道fifo或者/dev/fd目录下的某个文件相关联,就好像是command的输入、输出与另一个进程的输入输出流绑到了一起。 
    例如:

    $ echo "hello" > test.sh
    $ echo "world" >> test.sh
    $ cat test.sh
    hello
    world
    $ grep hello <(cat test.sh)
    hello
    $ echo aa bb cc dd >(awk '{print $1}')
    aa bb cc dd /dev/fd/63 
    $ echo aa bb cc dd > /dev/fd/63 >(awk '{print $1}')
    $ aa
    $ echo aa bb cc dd > /dev/fd/63 >(awk '{print $2}')
    $ bb
    $ echo aa bb cc dd > /dev/fd/63 >(awk '{print $3}')
    $ cc
    $ echo aa bb cc dd > /dev/fd/63 >(awk '{print $4}')
    $ dd

    9、单词拆分

    单词拆分发生在shell扩展中,相关的系统变量为IFS,即Internal Field Separator,默认值为<space><tab><newline>,这些分隔符出现在shell扩展结果的行首或行尾将被忽略,其它地方则作为分隔符把单词分隔开来。

    10、文件名扩展

    单词拆分以后,Bash会在每个单词中搜索“*”、“?”、“[”,如果找到其中一个,则进行模式匹配,内建命令shopt与模式匹配相关,下面说明模式匹配中的几个特殊符号。

    *    匹配任何字符串,包括空字符串。
    ?    匹配任意单个字符。
    [...]    匹配方括号中的任一字符。可以是一个范围表达式,由连字符连接一对字符,这个范围受当前语言环境的影响。如果方括号后面的第一个字符是“!”或“^”,则匹配任一没有出现在方括号中的字符。如果要匹配字符“-”,可以把它放在方括号中的第一个或最后一个位置,如果要匹配字符“]”,可以把它放在方括号中的第一个位置。
    [[:class:]]    通过class指定字符类别,class可以是POSIX标准中的下列关键字:alnum、alpha、ascii、blank、cntrl、digit、graph、lower、print、punct、space、upper、word、xdigit,其中word表示大小写字母、数字和下划线。
    [[=c=]]    匹配所有的字符c。
    [[.symbol.]]    匹配所有的符号symbol。
    ?(pattern-list)    匹配pattern-list零次或一次。
    *(pattern-list)    匹配pattern-list零次或多次。
    +(pattern-list)    匹配pattern-list一次或多次。
    @(pattern-list)    匹配pattern-list中的某个模式。
    !(pattern-list)    与pattern-list中的所有模式都不匹配的其它情形。

    11、引用删除

    经过上面提到的shell扩展以后,对于所有没有被引用的字符,包括反斜线“”、单引号“’”和双引号“””,若不是由shell扩展产生的,就会被删除,最终产生真正的结果。

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/iEearth/article/details/52548525
  • 相关阅读:
    每天一个linux命令(21):chgrp,chown,chmod
    设计模式之单例模式
    每天一个linux命令(20):find命令之exec
    每天一个linux命令(19):find 命令概览
    每天一个linux命令(18):locate 命令
    每天一个linux命令(17):whereis 命令
    【6折抢】戴尔i7新品Latitude高性能商用本
    Spring Cloud Gateway VS Zuul 比较,怎么选择?
    Zookeeper怎么实现分布式锁?
    数据库怎么分库分表,垂直?水平?
  • 原文地址:https://www.cnblogs.com/liujiacai/p/9008435.html
Copyright © 2020-2023  润新知