设为首页 收藏本站
查看: 677|回复: 0

shell十三问之8: $(())与$()还有${}差在哪?

[复制链接]

尚未签到

发表于 2015-10-26 10:12:41 | 显示全部楼层 |阅读模式

shell十三问之8: $(())与$()还有${}差在哪?




我们上一章介绍了()与{}的不同,

这次让我们扩展一下,看看更多的变化:

$()与${}又是啥玩意儿呢?


在bash shell中, $()与``(反引号)都是用来做

命令替换(command substitution)的。


所谓的命令替换与我们第五章学过的变量替换差不多,

都是用来重组命令行:

完成 `` 或者$()里面的

命令,将其结果替换出来,

再重组命令行。


例如:


$ echo the last sunday is $(date -d "last sunday" +%Y-%m-%d)


如此便可方便得到上一个星期天的日期了...^_^


在操作上, 用$()或``都无所谓,

只是我个人比较喜欢用$(),理由是:




  • ``(反引号)很容易与''(单引号)搞混乱,尤其对初学者来说。

    有时在一些奇怪的字形显示中,两种符号是一模一样的(只取两点)。

    当然了有经验的朋友还是一眼就能分辨两者。只是,若能更好的避免混乱,

    又何乐而不为呢? ^_^

  • 在多次的复合替换中, ``需要额外的转义(escape, )处理,而$()则比较直观。

    例如,一个错误的使用的例子:

    command1 `command2 `command3` `

    原来的本意是要在command2 `command3` ,

    先将command3替换出来给command2处理,

    然后再将command2的处理结果,给command1来处理。

    然而真正的结果在命令行中却是分成了`command2`与 ``。


正确的输入应该如下:


    command1 `command2 \`command3\` `


要不然换成$()就没有问题了:


    command1 $(commmand2 $(command3))


只要你喜欢,做多少层的替换都没有问题~~~^_^


不过,$()并不是没有弊端的...

首先,``基本上可用在所有的unix shell中使用,

若写成 shell script,其移植性比较高。

而$()并不是每一种shell都能使用,我只能说,

若你用bash2的话,肯定没问题... ^_^


接下来,再让我们看看${}吧...它其实就是用来做

变量替换用的啦。

一般情况下,$var与${var}并没有啥不一样。

但是用${}会比较精准的界定变量名称的范围,

比方说:


$ A=B
$ echo $AB


原本是打算先将$A的结果替换出来,

然后在其后补一个字母B;

但命令行上,

真正的结果却是替换变量名称为AB的值出来...

若使用${}就没有问题了:


$ A=B
$ echo ${A}B
$ BB


不过,假如你只看到${}只能用来界定变量名称的话,

那你就实在太小看bash了。


为了完整起见,我这里再用一些例子加以说明${}的一些

特异功能:

假设我们定义了一个变量file为:


file=/dir1/dir2/dir3/my.file.txt


我们可以用${}分别替换获得不同的值:



1. shell字符串的非贪婪(最小匹配)左删除



${file#*/}  #其值为:dir1/dir2/dir3/my.file.txt


拿掉第一个/及其左边的字符串,其结果为:

dir1/dir2/dir3/my.file.txt 。


${file#*.}  #其值为:file.txt


拿掉第一个.及其左边的字符串,其结果为:

file.txt 。



2. shell字符串的贪婪(最大匹配)左删除:



${file##*/} #其值为:my.file.txt


拿掉最后一个/及其左边的字符串,其结果为:

my.file.txt


${file##*.} #其值为:txt


拿掉最后一个.及其左边的字符串,其结果为:

txt



3. shell字符串的非贪婪(最小匹配)右删除:



${file%/*}  #其值为:/dir1/dir2/dir3


拿掉最后一个/及其右边的字符串,其结果为:

/dir1/dir2/dir3。


${file%.*}  #其值为:/dir1/dir2/dir3/my.file


拿掉最后一个.及其右边的字符串,其结果为:

/dir1/dir2/dir3/my.file。



4. shell字符串的贪婪(最大匹配)右删除:



${file%%/*}  #其值为:其值为空。


拿掉第一个/及其右边的字符串,其结果为:

空串。


${file%%.*}  #其值为:/dir1/dir2/dir3/my。


拿掉第一个.及其右边的字符串,其结果为:

/dir1/dir2/dir3/my。



Tips:
记忆方法:
#是去掉左边(在键盘上#在$的左边);
%是去掉右边(在键盘上%在$的右边);
单个符号是最小匹配;
两个符号是最大匹配;



5. shell字符串取子串:



${file:0:5} #提取最左边的5个字符:/dir1
${file:5:5} #提取第5个字符及其右边的5个字符:/dir2


shell字符串取子串的格式:${s:pos:length},

取字符串s的子串:从pos位置开始的字符(包括该字符)的长度为length的的子串;

其中pos为子串的首字符,在s中位置;

length为子串的长度;



Note: 字符串中字符的起始编号为0.



6. shell字符串变量值的替换:



${file/dir/path}  #将第一个dir替换为path:/path1/dir2/dir3/my.file.txt
${file//dir/path} #将全部的dir替换为path:/path1/path2/path3/my.file.txt


shell字符串变量值的替换格式:




  • 首次替换:

    ${s/src_pattern/dst_pattern} 将字符串s中的第一个src_pattern替换为dst_pattern。

  • 全部替换:

    ${s//src_pattern/dst_pattern} 将字符串s中的所有出现的src_pattern替换为dst_pattern.


7. ${}还可针对变量的不同状态(没设定、空值、非空值)进行赋值:





  • ${file-my.file.txt} #如果file没有设定,则使用

    使用my.file.txt作为返回值, 否则返回${file};(空值及非空值时,不作处理。);

  • ${file:-my.file.txt} #如果file没有设定或者${file}为空值,
    均使用my.file.txt作为其返回值,否则,返回${file}.(${file} 为非空值时,不作处理);

  • ${file+my.file.txt} #如果file已设定(为空值或非空值),
    则使用my.file.txt作为其返回值,否则不作处理。(未设定时,不作处理);

  • ${file:+my.file.txt} #如果${file}为非空值,
    则使用my.file.txt作为其返回值,否则,(未设定或者为空值时)不作处理。

  • ${file=my.file.txt} #如果file为设定,则将file赋值为my.file.txt,同时将${file}作为其返回值;否则,file已设定(为空值或非空值),则返回${file}。

  • ${file:=my.file.txt} #如果file未设定或者${file}为空值,
    则my.file.txt作为其返回值,

    同时,将${file}赋值为my.file.txt,否则,(非空值时)不作处理。

  • ${file?my.file.txt} #如果file没有设定,则将my.file.txt输出至STDERR,
    否侧,

    已设定(空值与非空值时),不作处理。

  • ${file:?my.file.txt} #若果file未设定或者为空值,则将my.file.txt输出至STDERR,否则,

    非空值时,不作任何处理。


Tips:
以上的理解在于,你一定要分清楚,unset与null以及non-null这三种状态的赋值;

一般而言,与null有关,若不带:, null不受影响;

若带 :, 则连null值也受影响。



8. 计算shell字符串变量的长度:${#var}



${#file}  #其值为27, 因为/dir1/dir2/dir3/my.file.txt刚好为27个字符。


9. bash数组(array)的处理方法




接下来,为大家介绍一下bash的数组(array)的处理方法。

一般而言, A="a b c def"

这样的变量只是将$A替换为一个字符串,

但是改为 A=(a b c def),

则是将$A定义为数组....



1). 数组替换方法可参考如下方法:


${A[@]} #方法一
${A
  • } #方法二


    以上两种方法均可以得到:a b c def, 即数组的全部元素。



    2). 访问数组的成员:


    ${A[0]}


    其中,${A[0]}可得到a, 即数组A的第一个元素,

    而 ${A[1]}则为数组A的第二元素,依次类推。



    3). 数组的length:


    ${#A[@]} #方法一
    ${#A
  • } #方法二


    以上两种方法均可以得到数组的长度: 4, 即数组的所有元素的个数。


    回忆一下,针对字符串的长度计算,使用${#str_var};

    我们同样可以将该方法应用于数组的成员:


    ${#A[0]}


    其中,${#A[0]}可以得到:1,即数组A的第一个元素(a)的长度;

    同理,${#A[3]}可以得到: 3, 即数组A的第4个元素(def)的长度。



    4). 数组元素的重新赋值:


    A[3]=xyz


    将数组A的第四个元素重新定义为xyz。



    Tips:
    诸如此类的...
    能够善用bash的$()与${}可以大大提高及

    简化shell在变量上的处理能力哦~~~^_^



    10. $(())作用:




    好了,最后为大家介绍$(())的用途吧:

    $(())是用来作整数运算的。


    在bash中, $(())的整数运算符号大致有这些:



    • +- * / #分别为"加、减、乘、除"。
    • % #余数运算,(模数运算)
    • & | ^ ! #分别为"AND、OR、XOR、NOT"运算。


    例如:


    $ a=5; b=7; c=2;
    $ echo $(( a + b * c ))
    19
    $ echo $(( (a + b)/c ))
    6
    $ echo $(( (a * b) % c ))
    1


    在$(())中的变量名称,

    可以在其前面加 $符号来替换,

    也可以不用,如:

    $(( $a + $b * $c )) 也可以得到19的结果。


    此外,$(())还可作不同进制(如二进制、八进制、十六进制)的运算,

    只是输出结果均为十进制的。


    echo $(( 16#2a )) #输出结果为:42,(16进制的2a)


    以一个实用的例子来看看吧 :

    假如当前的umask是022,那么新建文件的权限即为:


    $ umask 022
    $ echo "obase=8; $(( 8#666 & (8#777 ^ 8#$(umask)) ))" | bc
    644


    事实上,单纯用(())也可以重定义变量值,或作testing:


    a=5; ((a++)) #可将$a 重定义为6
    a=5; ((a--)) #可将$a 重定义为4
    a=5; b=7; ((a< b)) #会得到0 (true)返回&#20540;。


    常见的用于(())的测试符号有如下这些:



    符号
    符号名称

    <
    小于号
    >
    大于号
    <=
    小于或等于
    >=
    大于或等于
    ==
    等于
    !=
    不等于

    Note:
    使用(())作整数测试时,

    请不要跟[]的整数测试搞混乱了。
    更多的测试,我们将于第10章为大家介绍。



    怎样? 好玩吧... ^_^


    okay,这次暂时说这么多...


    上面的介绍,并没有详列每一种可用的状态,

    更多的,就请读者参考手册文件(man)吧...


    orginal  link:https://github.com/wzb56/13_questions_of_shell


    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
    2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
    3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
    4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
    5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
    6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
    7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
    8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

    所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-130860-1-1.html 上篇帖子: Windows Shell编程参考网址列表 下篇帖子: Shell Code 原理深入剖析
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    扫码加入运维网微信交流群X

    扫码加入运维网微信交流群

    扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

    扫描微信二维码查看详情

    客服E-mail:kefu@iyunv.com 客服QQ:1061981298


    QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


    提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


    本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



    合作伙伴: 青云cloud

    快速回复 返回顶部 返回列表