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

Shell中的一些常用特殊字符

[复制链接]

尚未签到

发表于 2015-10-26 11:51:10 | 显示全部楼层 |阅读模式
1、关于$
$是个在shell中有多种使用方式的东东。不经常使用时,也是很容易忘记的一个特殊标识符,记录一下比较常用的几种用法:


  • $# : 获得脚本传入参数的个数。
  • $? :  获得上面函数或脚本执行之后的返回值(或者叫退出码)。(默认成功执行之后返回0)
  • $$ :  获得当前所在脚本的进程ID号。(通常会被作为生成唯一标识的一种手段)
  • $! : 获得最后一个后台进程PID。(通常这个可以用来结合后台任务& 来完成一定时间内运行任务的需求:cmd & (sleep 10; kill -9 $! 2>/dev/null))
  • $() : 相当于``,也用作命令替换,即先执行括号中的命令,然后返回命令执行的结果。
  • $*/$@ : 获取传入脚本的全部参数。但两者在加上引号之后的行为有些差别,后者会把传入参数以空格为分割拆分成多个,前者则还是作为一个整体看待。另外,这个差异也跟脚本的传入参数是否使用了引号有关,具体看一下例子。

    • Bash代码   DSC0000.png

      • #a.sh为测试脚本,内容如下  
      • #!/bin/bash  
      • echo "The passed in parameters are : $@"  
      • echo 'Test $@ : '  
      • for arg in $@  
      • do  
      •   echo "$arg"  
      • done  
      • echo 'Test $*: '  
      • for arg in $*  
      • do  
      •   echo "$arg"  
      • done  
      • echo 'Test "$@" : '  
      • for arg in "$@"  
      • do  
      •   echo "$arg"  
      • done  
      • echo 'Test "$*": '  
      • for arg in "$*"  
      • do  
      •   echo "$arg"  
      • done  
      •   
      • ## 下面是几种不同调用输出的结果  
      • # use nothing  
      • ./a.sh a b c d e  
      • The passed in parameters are : a b c d e  
      • Test $@ :   
      • a  
      • b  
      • c  
      • d  
      • e  
      • Test $*:   
      • a  
      • b  
      • c  
      • d  
      • e  
      • Test "$@" :   
      • a  
      • b  
      • c  
      • d  
      • e  
      • Test "$*":   
      • a b c d e  
      • # use " "  
      • ./a.sh "a b c d e"  
      • The passed in parameters are : a b c d e  
      • Test $@ :   
      • a  
      • b  
      • c  
      • d  
      • e  
      • Test $*:   
      • a  
      • b  
      • c  
      • d  
      • e  
      • Test "$@" :   
      • a b c d e  
      • Test "$*":   
      • a b c d e  
      • # use ' '  
      • ./a.sh 'a b c d e'  
      • The passed in parameters are : a b c d e  
      • Test $@ :   
      • a  
      • b  
      • c  
      • d  
      • e  
      • Test $*:   
      • a  
      • b  
      • c  
      • d  
      • e  
      • Test "$@" :   
      • a b c d e  
      • Test "$*":   
      • a b c d e  

    • 当然,这个种表示还有很多细微的差别不太常用,具体的可以参考这里:http://www.tsnc.edu.cn/default/tsnc_wgrj/doc/abs-3.9.1_cn/html/internalvariables.html#APPREF

  • ${}: 变量替换

    • ${#var}:输出var变量的字符串长度。

      • Bash代码  

        • var=123456789;echo ${#var}  
        • 9   


    • ${var#string}/${var##string}/${var%string}/${var%%string}:字符串截取(string中支持Globbing风格的通配符*和?)

      • Bash代码  

        • var1=abcd12345abc6789  
        • pattern1=a*c  # *(通配符)匹配a - c之间的任意字符.  
        • #从左到右非贪婪式匹配,即匹配到最短的一个就停止,将匹配到的串截掉。  
        • echo '${var1#$pattern1} =' "${var1#$pattern1}"  # Output : ${var1#$pattern1} = d12345abc6789  
        • #从左到右贪婪式匹配,即匹配到最长一个才停止,将匹配到的串截掉。  
        • echo '${var1##$pattern1} =' "${var1##$pattern1}" # Output :  ${var1##$pattern1} = 6789  
        •   
        • pattern2=b*9    # 匹配'b''9'之间的任意字符  
        • #从右到左非贪婪式匹配,即匹配到最短的一个就停止,将匹配到的串截掉。   
        • echo '${var1%$pattern2} =' "${var1%$pattern2}" # Output : ${var1%$pattern2} = abcd12345a  
        • #从右到左贪婪式匹配,即匹配到最长的一个才停止,将匹配到的串截掉。  
        • echo '${var1%%$pattern2} =' "${var1%%$pattern2}" # Output : ${var1%%$pattern2} = a  
        • # 这关于#和%谁截掉左边,谁截掉右边的记法,最简单的就是看看键盘上他们在$符号的左右位置。  
        Bash代码  

        • #使用这种方式实现的basename的功能  
        • path_name=/home/bozo/ideas/thoughts.for.today  
        • t=${path_name##/*/}  
        • echo $t #Output: thoughts.for.today   


    • ${var:pos}/${var:pos:len}: 相当于Java中String的subString方法,也是bash中以index方式截取字符串的方法。但这种方式即使下标越界,也不会有任何错误输出。。。

      • Bash代码  

        • var1=abcd12345abc6789  
        • echo ${var1:0} # abcd12345abc6789  
        • echo ${var1:1} # bcd12345abc6789  
        • echo ${var1:0:1} # a  


    • ${var/Pattern/Replacement}: 使用Replacement来替换变量var中第一个匹配Pattern的字符串。

      • Bash代码  

        • var1=abcd-1234-defg;t=${var1/abcd/m*m-};echo $t  
        • # Output : m*m--1234-defg  
        • # pattern中同样支持*通配符,但同样也是Globbing风格。  
        • var1=abcd-1234-defg;t=${var1/a*d/m*m-};echo $t  
        • # Output : m*m-efg  


    • ${var//Pattern/Replacement}:同上,当时多了一个斜杠之后,标识不仅仅替换第一个匹配的字符串,而是全局替换。
    • ${var/#Pattern/Replacement}/${var/%Pattern/Replacement}: 这里#和%表示Pattern只匹配字符串的开头或者结尾,功能有点类似于RE中的^和$。

      • Bash代码  

        • v0=abc1234zip1234abc  
        • v1=${v0/#abc/ABCDEF}  
        • echo "v1 = $v1" # v1 = ABCDEF1234zip1234abc  
        • v2=${v0/%abc/ABCDEF}  
        • echo "v2 = $v2" # v2 = abc1234zip1234ABCDEF  
        • # 123 is neither the prefix nor suffix, so the String will not be replaced.  
        • v3=${v0/#123/000}  
        • echo "v3 = $v3" # v3 = abc1234zip1234abc  
        • v4=${v0/%123/000}  
        • echo "v4 = $v4" # v4 = abc1234zip1234abc  


    • ${array[@]}/${array
    • }: 获取数组的全部元素(${array[index]为获取数组中下标为index的那一个元素)。

      • Bash代码  

        • my_array=(a b c d e)  
        • echo 'Test ${my_array[@]}'  
        • for my in ${my_array[@]}  
        • do  
        •   echo $my  
        • done  
        • echo 'Test ${my_array
        • }'  
        • for my in ${my_array
        • }  
        • do  
        •   echo $my  
        • done  
        •   
        • #The following is the output  
        • Test ${my_array[@]}  
        • a  
        • b  
        • c  
        • d  
        • e  
        • Test ${my_array
        • }  
        • a  
        • b  
        • c  
        • d  
        • e   



  • $ : 在正则表达式(RE)中作为行结束符。
2、关于Globbing
Bash本身并不会识别正则表达式,在脚本中,使用RE的是命令和工具。比如sed、awk等工具。Bash仅仅做的是文件名的扩展(当然还有上面提到的关于字符串的替换时使用的通配符),也就是所谓的Globbing。Globbing所使用的通配符最常用的有这3个:*/?/^。
这里面最容易和标准正则表达式产生混淆的就是前面两个通配符。
在RE中,*和?的通配作用主要是基于某个特定的字符的,而在Globbing中,他们的通配作用却可以代表任何字符。具体看个例子:

Bash代码  

  • ls -l  
  • -rw-r--r--   1 sky  staff   3269  9 29 15:29 velocity.log  
  • -rw-r--r--   1 sky  staff      0 10  6 19:10 velocityab.log  
  • -rw-r--r--   1 sky  staff      0 10  6 19:10 velocityyy.log  
  •   
  • ##Globbing style  
  • ls -l *.log  
  • -rw-r--r--  1 sky  staff  3269  9 29 15:29 velocity.log  
  • -rw-r--r--  1 sky  staff     0 10  6 19:10 velocityab.log  
  • -rw-r--r--  1 sky  staff     0 10  6 19:10 velocityyy.log  
  • ##RE style, nothing output to the console  
  • ls -l|egrep "*.log"  
  • egrep: repetition-operator operand invalid  
  • ##RE style again  
  • ls -l|egrep "velocity*.log"  
  • -rw-r--r--   1 sky  staff   3269  9 29 15:29 velocity.log  
  • -rw-r--r--   1 sky  staff      0 10  6 19:10 velocityyy.log  
从上面的例子可以看出来,RE中,*是不能作为一个独立的“通配单元”存在的,但是Globbing中没有问题,但是需要注意的是,Globbing中*是不会通配以.开头的隐藏文件的。?会有上面类似的解释规则。所以在Globbing中,velocity.???可以被解释为velocity.log,但同样也可以被解释为velocity.123等。
3、关于各种[](包括[[]])


  • []用作条件测试:基本上等价于shell内建的test。最常见的就是if/while等后面的判断条件。
  • []用作数组元素:直接看例子

    • Bash代码  

      • my_array=(a b c d e);  
      • echo "The first element is : ${my_array[0]}" #The first element is : a   


  • []用作RE中的字符范围:匹配中括号中字符集中的某一个字符。常用的可以参考如下的这些形式:[xyz]/[c-n]/[B-Pa-m]/[a-z0-9]/[^b-d](这里的^标识取反了)
  • [[]]用作表达式的条件测试:它和[]的最大区别就是,内部支持&&/||/>/<等符号,这也是使得它的结构相对于[]更加通用。
4、关于整数运算扩展操作符(())
该结构允许整数运算和赋&#20540;。是Bash(注意,原生shell并不支持该结构)中C语言结构风&#26684;的一个表达式。常用的可以参考如下几种用法:((a=12))/((a&#43;&#43;))/((&#43;&#43;a))/((a--))/((--a))/((t = a<123?0:1)),这里需要注意两点:


  • 由于(())本身的C语言语法风&#26684;,(())内部在使用Bash变量时,是不需要$前缀标识它的引用形式的。
  • 注意上面例子中的最后一个,可以看出它支持多数编程语言中的典型的三元表达式哦。
5、关于重定向
Linux下,重定向输出的基本符号大家一般比较熟悉了。>表示覆盖式重定向,>>表示追加式重定向。这里需要强调的是:0,1,2这三个特殊的数字,作为3个特殊的文件描述符,已经被默认分配给了,stdin,stdout,stderr这3个特殊的“文件”。下面列出几个常用的利用重定向完成的小功能tip:


  • 清空文件内容: : >a.txt 清空a.txt文件的内容。(这里某些shell下,省略前面的冒号,直接使用 >a.txt也可以,但不是所有shell都支持这种语法,所以通用性不用加上冒号的版本)
  • 重定向错误输出到特定的文件中:比如,command 2>a.txt,执行command命令,同时将产生的错误输出信息,从终端中冲定向到a.txt中。
  • 将标准和错误输出全部输出到特定文件中:比较典型的用法就是不关心命令的任何输出,将所有输出信息都丢入垃圾桶:command >/dev/null 2>&1。这个表达式如果不理解含义,很容易记错,误用成下面这个样子:

    • command 2>&1 >/dev/null 这个表达式只能保证将stdout丢掉,但是如果有错误产生,还是会输出到屏幕上。原因是:命令解释到command 2>&1是,表示将stderr输出到stdout上(就是屏幕上),后面执行到>/dev/null时,表示将stdout输出丢掉。但是,在这之前,stderr已经被重定向到了当时的stdout(就是屏幕),所以这时的错误信息并不会丢掉,还是会输出到屏幕。
    • 如果你已经决定不关心任何命令的输出信息,又觉得上面的写法有点啰嗦,那可以试试这个写法: command &>/dev/null 这个写法会不管三七二十一,直接把所有输出信息全部重定向到/dev/null,这里完全省略了默认的文件描述符1和2.


运维网声明 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-130931-1-1.html 上篇帖子: shell 进制 转化 下篇帖子: linux中查看现在使用的shell是ksh还是bash?以及怎样修改?
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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