美文网首页
Linux(二)shell使用 多命令连接符 转义符 常用特殊字

Linux(二)shell使用 多命令连接符 转义符 常用特殊字

作者: 石志不渝 | 来源:发表于2023-09-03 09:25 被阅读0次

    一 多命令执行的连接

    共四个命令执行操作符,用于多命令同时执行时的连接符号。分别为:

    操作符 说明
    | 命令依照顺序执行
    ; 忽略各个命令成功与否,从左到右依次执行
    && 前一个命令执行成功后,执行后一个命令,否则不继续向下执行
    || 前一个命令执行失败后,执行后一个命令,如果前一个命令成功,则不继续执行

    1.1 管道

    上篇文章中,讲过 输入输出流 的概念,现在我们可以把每条运行的指令(实际是一个软件程序),想象为一个水管,每个水管都是左侧进水,右侧出水。
    下图以echo abc为例,echo为一个水管,左侧为标准输入中流入的abc,经过echo后流入屏幕进行显示

    echo

    管道的概念,是把很多水管连在一起,形成管道。比如两个命令 echo abcgrep a如下图:

    pipe

    echo接收abc作为参数,之后输出;此时因为后面接续着一个水管,数据流自然是流到下一个水管中,也就是echo\color{red}{输出}abc,成为了grep\color{green}{输入}grep指令的作用,是在输入中,找到可以与参数相匹配的内容,并显示匹配行。所以在屏幕上可以显示出abc的结果,实际指令的执行情况如下图

    实际指令执行情况

    再比如

    ls | wc -l
    

    ls 的输出,输入到 wc(word count)后,可以统计ls所列出的项目数量。

    wc
    管道小结: 以管道连接的指令,将会由左向右顺序执行;并且,左侧指令执行的输出,将作为右侧指令执行的输入。

    1.2 “与”连接

    && 连接的指令,左侧指令执行失败后,则右侧指令不再执行。相当于逻辑中的and(与)关系。以下指令中,文件tv_none.txt不存在。

    echo abc && ls tv_none.txt && ifconfig
    

    执行效果如下图,可以看到,当 ls指令报错后,ifconfig指令并未运行

    and

    1.3 “或”连接

    ; 无论左侧指令是否执行成功,均执行右侧指令。相当于逻辑中的or(或)关系。依然是上面的三条指令,改为使用;连接。

    echo abc; ls tv_none.txt; ifconfig
    

    运行效果如下图,可以看到一共\color{red}{3}部分输出,其中第二部分是报错信息。

    or

    1.3 “非”连接

    ||只有当左侧指令报错时,右侧指令才会执行。如果左侧指令成功,则右侧指令不再执行。相当于逻辑关系中的Not(非)。依然是上面的三条指令,需要把ls改为第一个执行,也就是放在最左侧,之后使用|| 连接

    ls tv_none.txt||echo abc||ifconfig
    

    运行效果如下图,可以看到ls指令报错后,依然执行了echo指令,但echo指令成功执行后,并未继续执行ifconfig指令。

    NOT

    二 转义符

    常用的转义符包括:\(反斜杠) ''(单引号) ""(双引号)

    2.1 \

    反斜杠,用于将特殊字符转化为普通字符,例如当我们键入Enter时,其实是向shell传递了一个换行符,shell在接收到换行符后开始执行指令,但是如果在命令的末尾加入\,则指令不会被执行,而是继续等待输入。

    ls \
    

    效果如下图,此时如果继续输入 -l,之后 键入Enter,则程序执行成功,与直接执行ls -l一样。

    ls ls -l

    2.2 ''""

    ''可以将 \color{red}{所有的}特殊字符转化为普通字符;""可以将\color{red}{部分}特殊字符转化为普通字符。依然是上面的指令,使用 ''包裹\,与使用""包裹''的效果是不同的。

    ls '\'
    ls "\"
    

    可以看到,当使用''包裹时,ls指令会把\当作要列出的对象;而使用""包裹时,与2.1中相同,依然保持了\的特性。

    单、双引号

    三 常用特殊字符

    除了上述转义符、操作符外、重定向外,还有一些常用的特殊字符。

    3.1 $

    用于获取变量的值。变量及常量的概念,在前述文章中已经讲过。bash的编程能力在前述文章中也曾提到。既然bash是可以编程的,那么对变量的支持则是理所当然的。在bash中,我们使用变量名=变量值的格式去声明一个变量,使用$变量名去获取这个变量的值。如下代码:

    file_name="test.txt"
    cat $file_name # $file_name是file_name的值
    

    在代码中$file_namefile_name的值,cat $file_name 等效于cat test.txt

    获取变量

    再比如,可以通过$直接获取到环境变量

    echo $PATH
    
    PATH
    注意:

    声明后的变量,仅在本shell中有效。

    3.2 反单引号 `

    反单引号,位于键盘左侧,从上向下的第二个键,英文状态下可直接输入。
    两个反单引号之间应该包裹一个指令,被包裹的指令将被执行,执行结果将作为字符串被输出。看示例:

    echo ls -l
    echo `ls -l`
    

    可以看到,当 echo后直接跟 ls -l时,ls -l直接作为一个字符串的输入,被echo输出到屏幕上。但当ls -l被反单引号包裹之后,echo输出到屏幕上的,成了ls -l执行后的结果。但很明显,和直接执行ls -l时,格式是不一样的,echo在进行输出的时候,将空白字符(包括换行符),替换成了空格。

    反单引号

    四 正则表达式

    4.1 正则表达式的基本用法

    正则表达式,是用来在一段内容中,做高级搜索和匹配的工具,与普通的搜索不同,正则表达式是一种模式搜索。
    需要说明的是,正则表达式并不是Linux系统特有的东西,它其实是很通用的,可以在很多编程语言、搜索工具中都可以使用的。
    首先可以回顾一下普通的搜索,当我们在文本文件中,需要搜索某个内容时,我们按下Ctrl + F组合键,然后输入我们要搜索的\color{red}{具体}内容,则可以进行搜索。

    普通搜索

    这里我加红了"具体"一词,是因为在普通搜索中,你必须要搜索很确切的东西,而不是某些更笼统的,比如还是上面的文字,我想要搜索出所有的数字。普通搜索是无法做到的,这时候,就需要用到正则表达式。

    sudo cat /mnt/share/mountain_tai.txt | grep '[0-9]*'
    
    正则匹配初步

    因为要完成复杂的模式匹配,所以需要约定一些用法,也就是正则表达式的语法、关键字等。下面就常用的用法分步进行介绍。

    1. ^。如果想找到行开头都有某个字符的所有行,那么我们需要用到^ (英文模式下,组合键Shift + 6)。比如我们想在文件中,搜索行开头有a的所有行,就可以用^a
    cat ./ta.txt #查看ta.txt 的内容,包括三行,其中两行以a开头
    cat ./ta.txt|grep '^a'
    
    以a开头
    1. $。与上述^ 对应的,是 $符。表示匹配行结尾是某个字符的所有行。依然是上面的文档,我们匹配结尾为cs的(不是必须只匹配一个字符,可以匹配连续的)。做匹配时$是放在\color{red}{结尾}的,比如cs$
      注意,我们这里说的,是正则表达式里的$ ,而非shell中用于获取变量的$
    cat ./ta.txt
    cat ./ta.txt|grep 'cs$'
    
    以cs结尾
    1. {}。想匹配某个字符多次,则可以使用{}.比如想找出连续两个s,可以用s{2}.
      注意,grep直接执行复杂正则时,有些符号需要转义,可以用 grep -E 或者egrep
    cat ./ta.txt
    cat ./ta.txt|grep 's{2}'  #此句无任何输出
    cat ./ta.txt|egrep 's{2}'
    cat ./ta.txt|grep 's\{2\}'
    cat ./ta.txt|grep -E 's{2}'
    
    匹配两次

    如果只是想匹配两次,直接使用两个重复字符也可以。比如此处使用grep 'ss'也是一样的效果

    1. {m,n},还可以匹配mn次,或者至少n
    cat ./ta.txt
    cat ./ta.txt|egrep 's{2,3}' 
    cat ./ta.txt|egrep 's{2,}'
    cat ./ta.txt|egrep 's{2}'
    
    多次匹配

    6.[]。 在正则开始时,我们匹配了数字,使用的[]符号,使用[],就是在搜索结果中,有[]内的任意内容,都将进行匹配。上述的数字匹配,一位的数字均为09。而使用+,则表示要匹配\color{red}{一次或多次}。所以[0-9]+则表示要匹配的内容里,必须包含一位或多位的0到9数字。

    cat ./ta.txt
    cat ./ta.txt|egrep '[0-9]+'
    
    数字匹配

    4.2 正则表达式的综合使用例子

    1. 一个经常使用的,是进行日期格式的匹配,比如当你要求用户输入的日期格式,必须是YYYY-MM-DD时,则可以使用正则表达式来匹配。
      年四位,月和日必须使用两位数,中间以-间隔:
    cat ./ta.txt|egrep '[0-9]{4}-[0-1]{1}[0-9]{1}-[0-3]{1}[0-9]{1}'
    

    在组织正则表达式时,需要严谨的逻辑,对要匹配模式的严谨总结,否则容易出现纰漏。如上述规则,其实并不能完全规范正确的日期


    日期匹配

    日期其实是要分情况的,不考虑的过于复杂。当十位是0-2时个位可以是0-9;当十位是3时,个位只能是0-1。此时需要分组进行匹配,用到(组一|组二|组n|)使用括号包括,用竖线分割,只要有一组被满足,则视为满足条件。
    下面的表达式,可以过滤掉日期为37的数据。但依然不是严谨的日期匹配。

    cat ./ta.txt|egrep '[0-9]{4}-[0-1]{1}[0-9]{1}-([0-2]{1}[0-9]{1}|[3]{1}[0-1]{1})'
    
    进一步组织日期匹配
    1. 对于爬虫来讲,需要对爬取的网页信息做提取。网页都是有规律的标签,此时正则表达式则更加好用。比如如下网页代码,是一份脱敏后的网页表格数据。
    
        <div class="column_search_result">
            
            <div class="content">
    
                <table width="100%" border="0" cellspacing="0" cellpadding="0" id="data_table_2" class="data_table">
                    <tbody>
                        <tr>
                            <th style="width: 5%; border-left: 1px solid #CFCFCF;">区域</th>
                            <th style="width: 12%;">项目名称</th>
                            <th style="width: 10%;">项目坐落</th>
                            <th style="width: 10%;">预售证号</th>
                            <th style="width: 17%;">开发企业</th>
                            <th style="width: 5%;">批准时间</th>
                        </tr>
    
                        <tr onmouseover="this.style.background=&#39;#f9f5ed&#39;" onmouseout="this.style.background=&#39;white&#39;" style="background: white;">
                            <td style="border-left: 1px solid #CFCFCF;"><div align="center">发区</div></td>
                                    
                            <td align="center"><a href="http://192.168.1.1:8000/reisPub/pub/preSaleBuildingStatist#" onclick="projectInfo(&#39;8177&#39;,&#39;3104854&#39;)">庭二期</a>  </td>
                            <td align="center">街以南,规路以东</td>
                            <td align="center">房预(销)xxxxx号</td>
                            <td align="center">xxxx公司</td>
                            <td align="center">2023-08-22</td>
                        </tr>
                                            <tr onmouseover="this.style.background=&#39;#f9f5ed&#39;" onmouseout="this.style.background=&#39;white&#39;" style="background: white;">
                            <td style="border-left: 1px solid #CFCFCF;"><div align="center">发区</div></td>
                                    
                            <td align="center"><a href="http://192.168.1.1:8000/reisPub/pub/preSaleBuildingStatist#" onclick="projectInfo(&#39;7331&#39;,&#39;3104853&#39;)">麓项目</a>  </td>
                            <td align="center">东街以北,天平路以西</td>
                            <td align="center">房预(销)xxxxx号</td>
                            <td align="center">xxxx公司</td>
                            <td align="center">2023-08-22</td>
                        </tr>
                                            <tr onmouseover="this.style.background=&#39;#f9f5ed&#39;" onmouseout="this.style.background=&#39;white&#39;" style="background: white;">
                            <td style="border-left: 1px solid #CFCFCF;"><div align="center">岳区</div></td>
                                    
                            <td align="center"><a href="http://192.168.1.1:8000/reisPub/pub/preSaleBuildingStatist#" onclick="projectInfo(&#39;7452&#39;,&#39;3101320&#39;)">度假区一期住宅</a>  </td>
                            <td align="center">环路以北、路以东</td>
                            <td align="center">房预(销)xxxxx号</td>
                            <td align="center">xxxx公司(山东)有限公司</td>
                            <td align="center">2023-08-15</td>
                        </tr>
                                            <tr onmouseover="this.style.background=&#39;#f9f5ed&#39;" onmouseout="this.style.background=&#39;white&#39;" style="background: white;">
                            <td style="border-left: 1px solid #CFCFCF;"><div align="center">区</div></td>
                                    
                            <td align="center"><a href="http://192.168.1.1:8000/reisPub/pub/preSaleBuildingStatist#" onclick="projectInfo(&#39;7448&#39;,&#39;3090592&#39;)">山玖玺</a>  </td>
                            <td align="center">路以南、路以东</td>
                            <td align="center">房预(销)xxxxx号</td>
                            <td align="center">xxxx公司</td>
                            <td align="center">2023-07-26</td>
                        </tr>
                                            <tr onmouseover="this.style.background=&#39;#f9f5ed&#39;" onmouseout="this.style.background=&#39;white&#39;" style="background: white;">
                            <td style="border-left: 1px solid #CFCFCF;"><div align="center">区</div></td>
                                    
                            <td align="center"><a href="http://192.168.1.1:8000/reisPub/pub/preSaleBuildingStatist#" onclick="projectInfo(&#39;7430&#39;,&#39;3089444&#39;)">著小区</a>  </td>
                            <td align="center">岱街以北,路以东</td>
                            <td align="center">房预(销)xxxxx号</td>
                            <td align="center">xxxx公司</td>
                            <td align="center">2023-07-24</td>
                        </tr>
                                            <tr onmouseover="this.style.background=&#39;#f9f5ed&#39;" onmouseout="this.style.background=&#39;white&#39;" style="background: white;">
                            <td style="border-left: 1px solid #CFCFCF;"><div align="center">岳区</div></td>
                                    
                            <td align="center"><a href="http://192.168.1.1:8000/reisPub/pub/preSaleBuildingStatist#" onclick="projectInfo(&#39;7460&#39;,&#39;3086713&#39;)">墅一期项目</a>  </td>
                            <td align="center">路以南、路以东、市体育中心以北</td>
                            <td align="center">房预(销)xxxxx号</td>
                            <td align="center">xxxx公司</td>
                            <td align="center">2023-07-19</td>
                        </tr>
                                            <tr onmouseover="this.style.background=&#39;#f9f5ed&#39;" onmouseout="this.style.background=&#39;white&#39;" style="background: rgb(249, 245, 237);">
                            <td style="border-left: 1px solid #CFCFCF;"><div align="center">岳区</div></td>
                                    
                            <td align="center"><a href="http://192.168.1.1:8000/reisPub/pub/preSaleBuildingStatist#" onclick="projectInfo(&#39;7460&#39;,&#39;3082774&#39;)">墅一期项目</a>  </td>
                            <td align="center">路以南、路以东、市体育中心以北</td>
                            <td align="center">房预(销)xxxxx号</td>
                            <td align="center">xxxx公司</td>
                            <td align="center">2023-07-12</td>
                        </tr>
                                            <tr onmouseover="this.style.background=&#39;#f9f5ed&#39;" onmouseout="this.style.background=&#39;white&#39;" style="background: white;">
                            <td style="border-left: 1px solid #CFCFCF;"><div align="center">新区</div></td>
                                    
                            <td align="center"><a href="http://192.168.1.1:8000/reisPub/pub/preSaleBuildingStatist#" onclick="projectInfo(&#39;7412&#39;,&#39;3082033&#39;)">府</a>  </td>
                            <td align="center">北天街以南、路以西</td>
                            <td align="center">房预(销)xxxxx号</td>
                            <td align="center">xxxx公司</td>
                            <td align="center">2023-07-11</td>
                        </tr>
                                            <tr onmouseover="this.style.background=&#39;#f9f5ed&#39;" onmouseout="this.style.background=&#39;white&#39;" style="background: white;">
                            <td style="border-left: 1px solid #CFCFCF;"><div align="center">区</div></td>
                                    
                            <td align="center"><a href="http://192.168.1.1:8000/reisPub/pub/preSaleBuildingStatist#" onclick="projectInfo(&#39;7445&#39;,&#39;3082602&#39;)">产业城项目西区</a>  </td>
                            <td align="center">碧霞路以东、省电力学校以南</td>
                            <td align="center">房预(销)xxxxx号</td>
                            <td align="center">xxxx公司(泰安)有限公司</td>
                            <td align="center">2023-07-11</td>
                        </tr>
                                            <tr onmouseover="this.style.background=&#39;#f9f5ed&#39;" onmouseout="this.style.background=&#39;white&#39;" style="background: white;">
                            <td style="border-left: 1px solid #CFCFCF;"><div align="center">区</div></td>
                                    
                            <td align="center"><a href="http://192.168.1.1:8000/reisPub/pub/preSaleBuildingStatist#" onclick="projectInfo(&#39;7448&#39;,&#39;3082603&#39;)">玖玺</a>  </td>
                            <td align="center">路以南、路以东</td>
                            <td align="center">房预(销)xxxxx号</td>
                            <td align="center">xxxx公司</td>
                            <td align="center">2023-07-11</td>
                        </tr>
                         
                    </tbody>
                </table>
            </div>
        </div>
        
    

    想提取出上述代码,列表中的数据,使用正则表达式可以很简单的实现

    sudo cat /mnt/share/house_info.html|egrep '(center"><a .*>(.*)</a>|<td align="center">[^<a](.*)</td>)'
    
    提取html内容

    可以让输出变得更加简洁

    sudo cat /mnt/share/house_info.html|sed -nr 's/<td align="center">[^<a](.*)<\/td>/\1/gp'
    

    改用sed命令的替换模式,sed 's/要替换的内容/替换成的内容/选项'在此处,要替换的内容使用正则表达式,<td align="center">[^<a](.*)<\/td>,替换成的内容\1表示正则表达式匹配的第一组内容,最后选项为gp其中g为全局匹配,p为打印匹配结果。

    sed

    相关文章

      网友评论

          本文标题:Linux(二)shell使用 多命令连接符 转义符 常用特殊字

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