使用Linux 的 gred、awk、sed 可以方便得处理文本,然而若要灵活使用这三个工具,首先必须理解正则表达式。这里先对正则表达式进行学习,做点记录,之后再练习一下文本处理工具的使用。
正则表达式
何为正则表达式?
正则表达式(Regular Expression)是指按照一定的规则使用特殊字符与普通字符组合而成的可以匹配一系列符合规定句法规则的字符串的单个字符串。
我个人的理解是我们为了找到带有某种特性的字符串,按照规定的句法规则,使用普通字符和带有特殊含义的特定字符写一个字符串,这个字符串就可以匹配一类带有某种特性的字符串。我们可以用正则表达式来方便得查找/替换/删除一行或多行文字字符串。
基础的正则表达式特殊字符如下:
RE字符 | 含义 |
---|---|
^word | 行首为word |
word$ | 行尾为word,注:^$ 就是匹配空行 |
. | 匹配任意一个字符 |
* | 匹配任意多个前一个字符,因此前面必须要有个字符,如果是.*就是匹配任意字符串了 |
\ | 转义字符,去除特殊符号的特殊意义 |
[list] | 匹配中括号内字符集任意一个的字符,例如a[bcd]e,可以匹配abe/ace/ade |
[^list] | ^表示反向选择,意思的不能匹配字符集中的字符,例如a[bcd]e,不能匹配abe/ace/ade |
[n1-n2] | 匹配中括号所示范围内的字符 |
\{n\} | 连续n个前一个字符,例如ha\{2}ha,可以匹配haaha |
\{n,\} | 至少连续n个前一个字符 |
\{n,m\} | 连续n到m个前一个字符,例如ha\{2,3\}ha,可以匹配haaha和haaaha |
另外还有一些常用的特殊符号:
特殊符号 | 含义 |
---|---|
[:alnum:] | 代表英文大小写字符和数字 |
[:alpha:] | 代表英文大小写字符 |
[:upper:] | 代表英文大写字符 |
[:lower:] | 代表英文小写字符 |
[:digit:] | 代表数字 |
还有一些常用的搭配'\'
组成的特殊字符
字符 | 含义 |
---|---|
\b | 单词边界 |
\B | 非单词边界 |
\w | 单个(字母,数字与_) 字符 |
\W | 单个非(字母,数字与_) 字符 |
注:好像不能直接用\d
表示[0-9]的数字。
扩展的正则表达式如下:
RE字符 | 含义 |
---|---|
+ | 连续前一个字符大于等于1次,如果用基本正则表达式要用\+ |
? | 前一个字符有或者没有,如果用基本正则表达式要用\? |
| | 或,如果用基本正则表达式也要在前面加上斜杠 |
{n} | 同基本正则的\{n\} |
{n,} | 同基本正则的\{n,\} |
{n,m} | 同基本正则的\{n,m\} |
() | 把一串字符用括号括起来形成组, 如果后面出现 \k 则是代表与第 k 个小括号中匹配到的数据,如果用基本正则表达式要用\(\) |
()+ | 连续多个组,例如A(BC)+D即为找出开头是A结尾是C中间有多个连续的BC的字符串 |
可以看到如果使用基本正则,往往需要转义字符'\'
配合才能表达出某些字符的特殊含义,例如想要表示前一个字符有或者没有,用基本的正则字符需要写成'\?'
,特别是括号,要写很多斜杠,非常繁琐。但这里有一个很有意思的问题,如果我就想匹配这些特殊字符的本意,不让他们表示出特殊含义,比如单纯匹配一个()
,显然用扩展字符就要进行一次转义了。
因此,转义的作用是,不支持正则符号的,比如 gred 不支持扩展正则'?'
,转变字符含义为正则,支持正则的,比如 egred 支持扩展正则'?'
,转变为普通字符含义。
注:grep 仅支持基础正则表达式,刚开始用 grep 试了好久一直没找出想要的内容,后来再查书才知道如果要使用延伸的正则表达式,像?,要可以使用 grep -E
, 或者直接用egrep
。
正则表达式示例
正则表达式的功能及其强大,然而写起来还是有点困难的,还是先多看再多写多练习。找了个例子来学习一下,即可以用来匹配IPv4地址的正则表达式:
^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$
IPv4地址分为四段,每段都是0-255,因此数值部分的模板可以说是相同的,但要注意前3段后面都有’.‘
,也应当匹配,因此不能直接pattern{4}
,而是(pattern\.){3}pattern
。对于数值部分,范围是0-255,我们将其拆分成几个部分:0-9,10-99,100-199,200-249,250-255。要用正则表达式匹配,分别为[0-9], [1-9][0-9], 1[0-9]{2}, 2[0-4][0-9], 25[0-5]
,其中前面两个可以合并为[1-9]?[0-9]
,之后,用'|'
拼接成用于匹配的模板:([1-9]?[0-9]|1[0-9]\{2\}|2[0-4][0-9]|25[0-5])
。注意为了不让匹配的字符串前后再有些稀奇古怪的东西,用'^'
和'$'
限制字符串即在行首又在行尾,那么它肯定是单独成一行。另外也可以把[0-9]
用[[:digit:]]
代替,但我觉得这样写起来反而麻烦了些,因此作罢。
注:^$
就是空行
grep
grep 分析行信息,若某行有我们想要的信息,就将该行列出。
再次提醒 grep 仅支持基础正则表达式,如果要使用延伸的正则表达式,可以使用 grep -E , 或者直接用egrep。
注意用 grep 查找字符串时,以行为单位进行数据选取。
命令:
grep [option] pattern [filename]
常用选项:
- -c:统计拥有与 pattern 匹配的字符串的行数
- -i:忽略字符大小写
- -n:显示匹配的行号
- -v:反向选择,显示没有与 pattern 匹配的字符串的行
- –color=auto:将匹配的部分加上颜色,注意可以设成默认
- -o:仅显示匹配到的字符串
- -q:静默模式,不输出任何信息
- -A:后接数字,如-A3,表示除列出该行外,后面3行也列出
- -B:后接数字,如-B3,表示除列出该行外,前面3行也列出
- -C:后接数字,如-C3,表示除列出该行外,前面3行也和后面3行都列出来
- -e:实现多个选项间的逻辑或关系 grep –e ‘A ’ -e ‘B’ file
- -E:使用扩展的正则表达式,相当于egrep
- -F:不支持正则表达式,相当于fgrep
grep 示例
grep的功能在于文本的查找。
示例1:
先就以查找IPv4地址为例作为示例。
先建立一个文件,写几行内容如下,我们用grep并用之前提到的正则表达式查找格式正确的IPv4地址
结果如下:
示例2:
这里对之前所提到的一个情况进行一个验证,即对于支持正则的工具,我们只想用字符原意,得进行转义,而对于支持不正则的工具就不用。
要匹配文本:(abc)
可以看到如果要找出(abc)
这个字符串,我们如果要用grep -E
或者egrep
,就要当心扩展正则字符没有进行转义。
总之,在使用grep工具进行字符串查找时要仔细确认所写的正则表达式到底能不能匹配我们想要的结果,这也是在使用所有文本处理工具时都要注意的一点。
示例3:
测试一下几个参数,文本用 Do not go gentle into that good night 这首诗。
先是-c
选项,看看能不能统计拥有与 pattern 匹配的字符串的行数
我们诗中找出a开头的单词,不加与加上'-c'
参数结果如下:
可以看到-c
选项可以帮助我们统计匹配的字符串所出现的行数。
再试试-v
选项
使用-v
选项可以选出没有出现匹配的字符串的行。
-A
选项效果:
sed
sed 拥有将数据进行替换、删除、新增、选定特定行等功能。可以理解为其功能在于文本的编辑。
命令:
sed [option] 动作 [filename]
常用选项:
- -n:仅显示处理后的行
- -e:直接在命令行模式上进行动作编辑(不加也行)
- -f:将动作写在某个文件内,使用
-f 动作文件名
可直接执行对应动作 - -i:直接修改文件的内容,而不是由屏幕输出
- -r:支持扩展正则表达式,默认是基础正则表达式
动作:
动作的标准格式为[n1[,n2]]funtion
若输入了[n1[,n2]]
表示对n1到n2行采取动作,如果不输入就是每行
具体的funtion可以是:
- a:将 a 的后面接的字符串插入下一行
- i:将 i 的后面接的字符串插入上一行
- c:用 c 的后面接的字符串替换指定的行
- d:删除匹配的内容
- p:将某个选中的数据打印出来,一般和 -n 一起用,否则屏幕上还是会输出全部内容,只是选中的输出2遍
- s:查找替换,格式为 s/要替换的内容/替换成的内容/g,此命令用于对部分数据进行替换,注意前面都是以行为单位进行处理的
sed 示例
在第2行和第3行后面分别插入string
在所有Do所在的行后面插入string
前插、替换、删除同理,不进行赘述。
再来看看打印,如下两种情况一个用了-n
,一个没用,差别较大,这就是为什么说p
通常和-n
一起用。
注意sed默认是基础正则,要让其支持扩展正则,则要加上 -r
,或者也可以-E
。下面就打印含有连续两个o
的行进行验证。
最后再来看看 sed 的数据替换功能,直接改诗不直观,我这里写一些正整数,用 sed 修改文本数据,使得1位数和2位数都变成128。另外这里我还试了一下-i
选项。用了-i
选项会修改原文件。
awk
awk被称为报告生成器,可用于读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表。awk主要是处理每一行字段内是数据。其功能在于对文本的数据分析及报告生成。
命令:
sed 'pattern {action}' [filename]
pattern 指示动作的触发条件,如未指定则处理每一行。指定方法可以是使用/ /
中间夹着字符串进行匹配,从而处理匹配字符串所在的行,也可以使用BEGIN和END分别表示所有行读取之前(无法处理首行)运行 action 以及所有行读取之后(可以处理尾行)运行 action,还可以用表达式指明要处理满足表达式的行等。
注:可以想象awk处理的数据是流输入的数据,把文件逐行的读入再按照单引号中指定的操作进行数据处理。
action 指示采取的动作,常用动作是利用 print 或 printf 列出文本内容。动作内也支持if(条件)
。
小插曲:变量
$0 :表示一整行
$1,$2,$3…:表示第1,2,3…个数据
NF:表示每行的字段数量
NR:表示目前所处理的行数
FS:输入字段的分隔字符
注:这里先简单记录几个,以后用到了再进行学习。
awk 示例
注意在使用 awk 执行动作时,动作用单引号' '
括住,如果在内部要用 print 打印内容,则除变量外的字符要用" "
括住。注意空格也是字符,所以只有在" "
中的空格才会打印出来。
例如想查看用户为 root 的进程,输出用户和进程号,命令与部分结果如下图所示:
现在再试验一下动作内的if(条件)
功能,选择进程号小于等于100,且为10的倍数的进程(为什么要这样选这些进程?只是演示着玩),命令与结果如下图所示:
除了直接显示,动作内还可以对数据作运算再显示,这里又涉及一个格式符的问题,在这里就不展开来记录格式符的表示方法了,反正和 C 中的差不多,例如表示一个浮点数用%m.nf
,m表示共m个数字,n表示n位小数。
这里简单演示一下,搞一个简单的文本如下,算一下每个人这三天一共和平均跑了多少公里,这个简单的操作这里尝试搞了好几次没搞出来,首先不能用print,如果用print会把标识符也输出来,还有动作中各语句要用分号';'
隔开,就像写C一样。
尾声:这篇笔记记录得有些杂乱,因为我是一边学习一边操作一边记录,经常就是后面发现啥就补上去,发现不对就改,所以笔记结构比较破碎,内容也没有详略得当,或许还有不少小错误。另外Linux正则表达式还有gred、awk、sed的知识点还有很多,我这里记录的只是冰山一角,甚至连一角都算不上。冰山的其他部分,还是需要在今后不断得深入探索。
今天的文章linuxgrep正则表达式_awk 正则表达式提取分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/86382.html