雨田风云 發表於 2023-11-17 10:11:05

Shell 正则表达式及综合案例及文本处理工具详解

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">一、常规匹配</a></li><li><a href="#_label1">二、常用特殊字符</a></li><li><a href="#_label2">三、匹配手机号</a></li><li><a href="#_label3">四、案例之归档文件</a></li><li><a href="#_label4">五、案例之定时归档文件</a></li><li><a href="#_label5">六、Shell文本处理工具</a></li><ul class="second_class_ul"><li><a href="#_lab2_5_0">1. cut工具</a></li><li><a href="#_lab2_5_1">2. awk工具</a></li></ul><li><a href="#_label6">实例操作</a></li><ul class="second_class_ul"><li><a href="#_lab2_6_2">1. 搜索passwd文件以root关键字开头的所有行,并输出该行的第7列</a></li><li><a href="#_lab2_6_3">2. 搜索passwd文件以root关键字开头的所有行,并输入该行的第1列和第7列,中间以&quot;,&quot;分割</a></li><li><a href="#_lab2_6_4">3. 只显示/etc/passwd 的第一列和第七列,以逗号分割,且在所有行前面添加列名&quot;start&quot;在最后一行添加&quot;over&quot;</a></li></ul><li><a href="#_label7">内置变量</a></li><ul class="second_class_ul"><li><a href="#_lab2_7_5">1. 统计passwd文件名,每行的行号,每列的列数</a></li><li><a href="#_lab2_7_6">2. 查询ifconfig命令输出结果中的空行所在行号</a></li></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>一、常规匹配</h2>
<p>一串不包含特殊字符的正则表达式匹配它自己</p>
<p>例子,比如说想要查看密码包含root字符串的,可以这样写</p>
<blockquote><p>cat /etc/passwd | grep root</p></blockquote>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202311/2023111710061918.png" /></p>
<p class="maodian"><a name="_label1"></a></p><h2>二、常用特殊字符</h2>
<table><tbody><tr><td>特殊字符</td><td>作用</td></tr><tr><td>^</td><td>匹配一行的开头</td></tr><tr><td>$</td><td>匹配一行的结束</td></tr><tr><td><p>.</p></td><td>匹配任意一个字符</td></tr><tr><td>*</td><td>*不单独使用,他和上一个字符连用,表示匹配上一个字符0次或者多次</td></tr><tr><td>[]</td><td>[]表示匹配某个范围内的一个字符</td></tr><tr><td>\</td><td>表示转义字符,一般和特殊字符连用表示特殊字符本身</td></tr></tbody></table>
<p>例1:匹配以a字符开头的:</p>
<blockquote><p>cat /etc/passwd | grep ^a&nbsp;</p></blockquote>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202311/2023111710061919.png" /></p>
<p>例子2:匹配以e字符结尾</p>
<blockquote><p>cat /etc/passwd | grep e$</p></blockquote>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202311/2023111710061920.png" /></p>
<p>例子3:匹配任一个字符</p>
<blockquote><p>cat /ect/passwd | grep r.t</p>
<p>cat /ect/passwd | grep r..t</p></blockquote>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202311/2023111710061921.png" /></p>
<p>例子4:查询包含以字符r开头,t结尾的字符串</p>
<blockquote><p>cat /etc/passwd | grep r.*t</p></blockquote>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202311/2023111710061922.png" /></p>
<p> ------匹配6或者8<br /> ------匹配一个0-9 的数字<br />* ------匹配任意长度的数字字符串<br /> ------匹配一个 a-z 之间的字符<br />* -----匹配任意长度的字母字符串<br /> ---匹配 a-c 或者 e-f之间的任意字符</p>
<p>用法例子看下图吧:</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202311/2023111710061923.png" /></p>
<p>例子6:假如说我们想查找n_test.sh文件包含$符的那这就需要用到转义字符</p>
<blockquote><p>cat /scripts/n_test.sh | grep &#39;\$&#39;</p></blockquote>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202311/2023111710061924.png" /></p>
<p class="maodian"><a name="_label2"></a></p><h2>三、匹配手机号</h2>
<p>我们都知道手机号是由第一位数字是1,第二位是3,4,5,7,8,9;其余数字随便。总共十一位数字,因此我们可以得出</p>
<blockquote><p>&quot;1569656955&quot; | grep ^1$</p></blockquote>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202311/2023111710061925.png" /></p>
<p>看上图可以得知,第一个数字符合手机号形式,而第二个明显不符合。但是这样【0-9】太多了,比较繁琐,我们就可以在后面用一个大括号表示出现次数来代替重复的0-9;但是要在正则表达式之前加入-E选项,如下:</p>
<blockquote><p>grep -E ^1{9}$</p></blockquote>
<p style="text-align:center"><img alt="" height="184" src="https://img.jbzj.com/file_images/article/202311/2023111710061926.png" width="739" /></p>
<p>大于小于11位数字都是不符合的&nbsp;</p>
<p class="maodian"><a name="_label3"></a></p><h2>四、案例之归档文件</h2>
<p>实际生产应用中,往往需要对重要的数据进行归档备份</p>
<blockquote><p><strong>需求:</strong>实现一个目录归档备份的脚本,输入一个目录名称,将目录下所有文件按天归档保存,并将归档日期附加在文档文件名上,放在根目录下(/archive)<br />这里用到的归档命令: tar</p></blockquote>
<p>后面可以加上 -c 选项表示归档,加上 -z 选项表示同时进行压缩得到的文件后缀名为 .tar.gz;不过要注意的是可能还是需要加上P选项代表允许我们使用绝对路径进行归档。</p>
<div class="jb51code"><pre class="brush:bash;">#!/bin/bash
# 首先判断输入的参数个数是否为1
if [ $# -ne 1 ]
then
    echo "参数个数错误!应该输入一个参数作为归档目录名"
    exit
fi
# 从参数中获取目录名称,查看目录名称是否存在
if [ -d $1 ]
then
    echo
else
    echo
    echo "目录不存在!"
    echo
    exit
fi
# 获取绝对路径
DIR_NAME=$(basename $1)
DIR_PATH=$(cd $(dirname $1);pwd)
# 获取当前日期,归档文件名拼接成日期
DATE=$(date +%y%m%d)
# 订阅生成归档文件名称
FILE=archive_${DIR_NAME}_$DATE.tar.gz
# 订阅生成归档文件的路径
DEST=/archive/$FILE
# 开始归档目录文件
echo "开始归档...."
echo
# -c 归档 z 压缩 f可视化
tar -czPf $DEST $DIR_PATH/$DIR_NAME
# 判断上面文件归档文件操作是否成功
if [ $? -eq 0 ]
then
    echo
    echo "归档成功"
    echo "归档的文件为:$DEST"
    echo
else
    echo "归档出现问题"
    echo
fi
exit</pre></div>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202311/2023111710061927.png" /></p>
<p class="maodian"><a name="_label4"></a></p><h2>五、案例之定时归档文件</h2>
<p>比如说我们想要1分钟归档文件一次;就可以设置定时器如下:</p>
<blockquote><p>*/1 * * * * /archive/archive_test.sh /scripts</p></blockquote>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202311/2023111710061928.png" /></p>
<p>可以看得出确实添加了一个归档文件&nbsp;</p>
<p class="maodian"><a name="_label5"></a></p><h2>六、Shell文本处理工具</h2>
<p class="maodian"><a name="_lab2_5_0"></a></p><h3>1. cut工具</h3>
<p>cut 的工作就是&ldquo;剪&rdquo;,具体的说就是在文件中负责剪切数据用的。<br />cut 命令从文件的每行剪切字节、字符和字段并将这些字节、字符和字段输出</p>
<p><strong>基本用法</strong></p>
<blockquote><p>cut [选项参数] filename</p></blockquote>
<p><strong>选项参数</strong></p>
<p>选项参数功能-f列号,提取第几列-d分隔符,按照指定分隔符分割列,默认是制表符&quot;\t&quot;-c按字符进行切割,后加n表示取第几列 比如-c 1</p>
<p>比如一个文本文件有以下诗歌:</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202311/2023111710061929.png" /></p>
<p>比如说我们需要提取第一列,那应该这样写,按空格指定分割第一列;如下:</p>
<blockquote><p>cut -d &quot; &quot; -f 1 cut_test.txt</p></blockquote>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202311/2023111710061930.png" /></p>
<p>假如我们想要提取第一和第四列,可以这样写:&nbsp;</p>
<blockquote><p>cut -d &quot; &quot; -f 1,4&nbsp;cut_test.txt</p></blockquote>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202311/2023111710061931.png" /></p>
<p>比如说我们想知道ens33网卡的所有IP,那么首先应该是ifconfig ens33,然后管道符|,再然后正则表达式获取ip 最后利用管道符切割。</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202311/2023111710061932.png" /></p>
<p>因为ip在第十列,因此-f后面跟10;整体写法如下:</p>
<blockquote><p>ifconfig ens33 | grep netmask | cut -d &quot; &quot; -f 10</p></blockquote>
<p class="maodian"><a name="_lab2_5_1"></a></p><h3>2. awk工具</h3>
<p>一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理</p>
<p><strong>基本用法</strong></p>
<blockquote><p>awk [选项参数] &#39;/pattern1/{action1}/pattern2/{action2}...&#39; filename</p></blockquote>
<p>&nbsp;pattern:表示awk 在数据中查找的内容,就是匹配模式<br />action:在找到匹配内容时所执行的一系列命令</p>
<p>选项参数功能-F指定文件分割符-v分支一个用户定义变量</p>
<p>不过有些版本的系统是不支持awk工具的,那么如何查看自己系统是否支持awk只需要输入以下句子即可:</p>
<blockquote><p>which awk</p></blockquote>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202311/2023111710061933.png" /></p>
<p>出现上面那段话说明你的系统是支持awk工具的</p>
<p class="maodian"><a name="_label6"></a></p><h2>实例操作</h2>
<p class="maodian"><a name="_lab2_6_2"></a></p><h3>1. 搜索passwd文件以root关键字开头的所有行,并输出该行的第7列</h3>
<blockquote><p>cat /etc/passwd | awk -F &quot;:&quot; &#39;/^root/ {print&nbsp;$7}&#39;</p></blockquote>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202311/2023111710062034.png" /></p>
<p class="maodian"><a name="_lab2_6_3"></a></p><h3>2. 搜索passwd文件以root关键字开头的所有行,并输入该行的第1列和第7列,中<br />间以&quot;,&quot;分割</h3>
<blockquote><p>cat /etc/passwd | awk -F &quot;:&quot; &#39;/^root/ {print $1 &quot;,&quot; $7}&#39;</p></blockquote>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202311/2023111710062035.png" /></p>
<p class="maodian"><a name="_lab2_6_4"></a></p><h3>3. 只显示/etc/passwd 的第一列和第七列,以逗号分割,且在所有行前面添加列<br />名&quot;start&quot;在最后一行添加&quot;over&quot;</h3>
<blockquote><p>&nbsp;cat /etc/passwd | awk -F &quot;:&quot; &#39;/^root/ {print $1&quot;,&quot; $7} END{print &quot;over&quot;}&#39;</p></blockquote>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202311/2023111710062036.png" /></p>
<p>4. 将passwd文件中的用户id增加数值1并输出&nbsp;</p>
<blockquote><p>cat /etc/passwd | awk -F &quot;:&quot; &#39;{print $3+1}&#39;</p></blockquote>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202311/2023111710062037.png" /></p>
<p class="maodian"><a name="_label7"></a></p><h2>内置变量</h2>
<p>变量说明FILENAME文件名NR已读记录数(行号)NF浏览记录的域的个数(切割后,列的个数)</p>
<p>示例操作</p>
<p class="maodian"><a name="_lab2_7_5"></a></p><h3>1. 统计passwd文件名,每行的行号,每列的列数</h3>
<blockquote><p>cat /etc/passwd | awk -F &quot;:&quot; &#39;{print &quot; 文件名:&quot; FILENAME &quot;\t行号:&quot; NR &quot;\t列数: &quot; NR}&#39; /etc/passwd</p></blockquote>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202311/2023111710062038.png" /></p>
<p class="maodian"><a name="_lab2_7_6"></a></p><h3>2. 查询ifconfig命令输出结果中的空行所在行号</h3>
<blockquote><p>ifconfig | awk &#39;/^$/ {print&quot;空行: &quot; NR}&#39;</p></blockquote>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202311/2023111710062039.png" /></p>
頁: [1]
查看完整版本: Shell 正则表达式及综合案例及文本处理工具详解