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

Linux Shell的通配符与正则表达式

[复制链接]

尚未签到

发表于 2015-10-26 10:42:56 | 显示全部楼层 |阅读模式
Overview
wildcard是由shell处理的, 它只会出现在 commandargument 里——既不用在 command_name里, 也不用在 options 上。当在argument中碰到Wildcard时,shell会将其当作路径或文件名去在磁盘上搜寻可能的匹配:若符合要求的匹配存在,则进行代换(路径扩展);否则就将该wildcard作为一个普通字符传递给command,交由command自行处理。总而言之,wildcard 实际上就是一种shell实现的路径扩展功能。在 wildcard 被处理后, shell会先完成该命令的重组,然后再继续处理重组后的命令,直至执行该命令。
       例如,若当前目录下有Cha1Cha2Des三个文件,而我想用grepDes中搜索包含字符串Cha的行,于是写出命令如下:
grep Cha* Des              

当该命令交由shell处理时,首先会将Cha*中的*当作是一个wildcard,于是就会在当前目录中搜索可能的匹配。*作为wildcard而言匹配的是0个或多个的任意字符,于是文件Cha1Cha2符合匹配要求,shell自行完成了该命令的重组,重组后的命令为:
grep Cha1 Cha2 Des      

而这才是最终执行的命令的文本形式。所以命令实际上的动作是试图在文件Cha2Des中寻找包含Cha1字符串的行。这和期望grep所作的动作是大相径庭的。
       可是,如果当前目录下没有可以匹配Cha*的文件或是文件夹(路径),那么shell会因为找不到可能的匹配而放弃*号的代换,将其传递给command处理,重组后的命令如下:
grep Cha* Des              

这也是该情况下最终执行的命令的文本形式。在这种情况下命令的动作和预期的动作却也不是一致的。因为当*号交给grep处理时,*号将不再是表示0个或多个任意的字符了——这是它作为wildcard,在shell中处理时的含义——在grep的处理中,*号是被当作正则表达式中的符号,表示的是其前面的字符出现0次或多次。
若是在第一种情况下,如何才能使重组后的命令为命令,而非命令呢?在shell的命令中,所有的文字可以分为meta literalliteral就是普通的纯文字,对于shell来说没有什么特别的意义;meta则是shell中具有特定功能的特殊保留字符,如< > |等。不严格区分的话,wildcard也可以归入这一类。也就是说,meta就是会在shell中被处理的从而在最终用于执行的命令中丧失了其自身文本形式的特殊字符(从这个角度来说,将wildcard归入meta是有些不妥的,因为wildcard的有可能被替换掉也有可能不被替换)。若是希望能够将shell中的meta以其文本形式进入command的最终执行形态中——像前面我们所希望的一样,就必须告诉shell不要对meta进行处理,command需要使用它们的文本形式。这个工作则是由shell quoting(转义)来完成的。这种处理正是使用regular expression(正则表达式)所必需要用到的:因为regular expression(正则表达式)中有许多特殊字符(可以看作是RE中的meta)和shell中的metawildcard是相同的,所以为了让那些regular expression中的特殊字符能够通过shell传入regular expression就必须对其进行转义。同样,在那些定义了自有的meta的命令中,若是自有的metashell中的metawildcard重复,也要用到shell quoting,如tr

Wildcard
*     匹配 0 或多个字符
?      匹配任意单一字符

                  匹配 list 中的任意单一字符
    [!list]      匹配不在 list 中的任意单一字符
    {string1,string2,...}              匹配 sring1 string2 (或更多)其一字符串
    例:
    a*b  ab之间可以有任意长度的任意字符, 也可以一个也没有, aabcb, axyzb, a012b, ab
    a?b  ab之间必须也只能有一个字符, 可以是任意字符, aab, abb, acb, a0b
    a[xyz]b   ab之间必须也只能有一个字符, 但只能是 x y z, : axb, ayb, azb
    a[!0-9]b  ab之间必须也只能有一个字符, 但不能是阿拉伯数字, axb, aab, a-b
    a{abc,xyz,123}b    ab之间只能是abcxyz123这三个字符串之一。

    shell中的meta
    下面是一些常用的:
    IFS   <space> <tab> <enter> 三者之一组成(我们常用 space )
    CR    <enter> 产生。
    =     设定变量。
    $     作变量或运算替换(请不要与 shell prompt 搞混了)
    >     重导向 stdout
    <     重导向 stdin
    |      命令管线。
    &    重导向 file descriptor ,或将命令置于背境执行。
    ( )    将其内的命令置于 nested subshell 执行,或用于运算或命令替换。
    { }   将其内的命令置于 non-named function 中执行,或用在变量替换的界定范围。
    ;      在前一个命令结束时,而忽略其返回值,继续执行下一个命令。
    &&  在前一个命令结束时,若返回值为 true,继续执行下一个命令。
    ||      在前一个命令结束时,若返回值为 false,继续执行下一个命令。
    !      执行 history 列表中的命令。

    Shell Quoting
    一共有三种转义字符,它们实际上也可以看作是shell中的meta
    ‘’(单引号)
    又叫hard quote,其内部所有的shell meta都会被关掉。注意,hard quote中不允许出现’(单引号)
    “”(双引号)
           又叫soft quote,其内部只允许出现特定的shell meta
           $     用于参数代换
           `      反引号,用于命令代换
           /$    实现美元标志
           /’     实现反引号的文本化(去除反引号的特殊意义)
           /”     实现双引号的文本化(去除双引号的特殊意义)
           //     实现反斜杠的文本化(去除反斜杠的特殊意义)
           注意,在soft quote中单引号没有特殊意义,就是文本。
    /(反斜杠)
           又叫escape,去除其后紧跟的metawildcard的特殊意义。
    实际上quote的使用就是为了跳过shell对特殊字符的处理。

    Regular Expression
    锚点(anchor)
    用以标识 RE 于句子中的位置所在. 常见有:
    ^     表示句首. ^abc 表示以 abc 开首的句子.
    $     表示句尾. abc$ 表示以 abc 结尾的句子.
    /<    表示词首. /<abc 表示以 abc 开首的词.
    />    表示词尾. abc/> 表示以 abc 结尾的词.
    修饰字符(modifier)
    独立表示时本身不具意义, 专门用以修改前一个字元集的出现次数. 常见有:
    *     表示前一个字元集的出现次数为0或多次。如ab*c表示ac之间可有0或多个b存在。
    ?      表示前一个字元集的出现次数为01次。如ab?c表示ac之间可有01b存在。
    +     表示前一个字元集的出现次数为1或多次。如ab+c表示ac之间可有1或多个b存在。
    {n}  表示前一个字元集的出现次数必须为n. ab{3,}c表示 ac之间必须有3b存在。
    {n,} 表示前一个字元集的出现次数至少为n. ab{3,}c表示ac之间至少有3b存在。
    {n,m}     表示前一个字元集的出现次数为nm. ab{3,5}c表示ac之间有35b存在。

    总结
    总的来说,正是因为shell中的metawildcard有时会和command中的meta相同,为了让command中的meta不被shell解析以至于改变,就必须用shell quoting来保证其文字不变性。

    附:shell脚本的解释过程
    DSC0000.png
    需要注意的是,double quote中的内容跳过了1-4步和9-10步,single quote中的内容跳过了1-10步。也就是说,double quote只经过参数扩展、命令代换和算术代换就可以送入执行步骤,而single quote直接会被送入执行步骤。而且,无论是double quote还是single quote在执行的时候能够告诉各个命令自身内部是一体的,但是其本身在执行时是并不是命令中文本的一部分。

    Lsdetail=”ls –l”

    $Lsdetail

      执行的就是ls –l,而double quote并不是执行命令的一部分。
                 版权声明:本文为博主原创文章,未经博主允许不得转载。

运维网声明 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-130884-1-1.html 上篇帖子: learning bash shell 学习笔记(一) 下篇帖子: SHELL病毒简介
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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