当前位置: 首页>后端>正文

Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式

一 多命令执行的连接

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

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

1.1 管道

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

Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第1张
echo

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

Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第2张
pipe

echo接收abc作为参数,之后输出;此时因为后面接续着一个水管,数据流自然是流到下一个水管中,也就是echoLinux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,\color{red}{输出},第3张abc,成为了grepLinux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,\color{green}{输入},第4张grep指令的作用,是在输入中,找到可以与参数相匹配的内容,并显示匹配行。所以在屏幕上可以显示出abc的结果,实际指令的执行情况如下图

Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第5张
实际指令执行情况

再比如

ls | wc -l

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

Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第6张
wc

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

1.2 “与”连接

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

echo abc && ls tv_none.txt && ifconfig

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

Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第7张
and

1.3 “或”连接

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

echo abc; ls tv_none.txt; ifconfig

运行效果如下图,可以看到一共Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,\color{red}{3},第8张部分输出,其中第二部分是报错信息。

Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第9张
or

1.3 “非”连接

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

ls tv_none.txt||echo abc||ifconfig

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

Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第10张
NOT

二 转义符

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

2.1 \

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

ls \

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

Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第11张
ls
Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第12张
ls -l

2.2 ''""

''可以将 Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,\color{red}{所有的},第13张特殊字符转化为普通字符;""可以将Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,\color{red}{部分},第14张特殊字符转化为普通字符。依然是上面的指令,使用 ''包裹\,与使用""包裹''的效果是不同的。

ls '\'
ls "\"

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

Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第15张
单、双引号

三 常用特殊字符

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

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

Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第16张
获取变量

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

echo $PATH
Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第17张
PATH

注意:

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

3.2 反单引号 `

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

echo ls -l
echo `ls -l`

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

Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第18张
反单引号

四 正则表达式

4.1 正则表达式的基本用法

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

Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第20张
普通搜索

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

sudo cat /mnt/share/mountain_tai.txt | grep '[0-9]*'
Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第21张
正则匹配初步

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

  1. ^。如果想找到行开头都有某个字符的所有行,那么我们需要用到^ (英文模式下,组合键Shift + 6)。比如我们想在文件中,搜索行开头有a的所有行,就可以用^a
cat ./ta.txt #查看ta.txt 的内容,包括三行,其中两行以a开头
cat ./ta.txt|grep '^a'
Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第22张
以a开头
  1. $。与上述^ 对应的,是 $符。表示匹配行结尾是某个字符的所有行。依然是上面的文档,我们匹配结尾为cs的(不是必须只匹配一个字符,可以匹配连续的)。做匹配时$是放在Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,\color{red}{结尾},第23张的,比如cs$
    注意,我们这里说的,是正则表达式里的$ ,而非shell中用于获取变量的$
cat ./ta.txt
cat ./ta.txt|grep 'cs$'
Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第24张
以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}'
Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第25张
匹配两次

如果只是想匹配两次,直接使用两个重复字符也可以。比如此处使用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}'
Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第26张
多次匹配

6.[]。 在正则开始时,我们匹配了数字,使用的[]符号,使用[],就是在搜索结果中,有[]内的任意内容,都将进行匹配。上述的数字匹配,一位的数字均为09。而使用+,则表示要匹配Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,\color{red}{一次或多次},第27张。所以[0-9]+则表示要匹配的内容里,必须包含一位或多位的0到9数字。

cat ./ta.txt
cat ./ta.txt|egrep '[0-9]+'
Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第28张
数字匹配

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}'

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


Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第29张
日期匹配

日期其实是要分情况的,不考虑的过于复杂。当十位是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})'
Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第30张
进一步组织日期匹配
  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>区域</th>
                        <th>项目名称</th>
                        <th>项目坐落</th>
                        <th>预售证号</th>
                        <th>开发企业</th>
                        <th>批准时间</th>
                    </tr>

                    <tr onmouseover="this.style.background=&#39;#f9f5ed&#39;" onmouseout="this.style.background=&#39;white&#39;">
                        <td><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;">
                        <td><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;">
                        <td><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;">
                        <td><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;">
                        <td><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;">
                        <td><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;">
                        <td><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;">
                        <td><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;">
                        <td><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;">
                        <td><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>)'
Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第31张
提取html内容

可以让输出变得更加简洁

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

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

Linux(二)shell使用 多命令连接符 转义符 常用特殊字符 正则表达式,第32张
sed

https://www.xamrdz.com/backend/3n31938393.html

相关文章: