本文共 2638 字,大约阅读时间需要 8 分钟。
一、前言
在我们初学Liunx时,就会遇到一拦路虎,那就是“正则表达式”。原因在于其结构的复杂性和逻辑性较强,需大量的练习才能将其掌握。故本文主要整理总结了正则表达式在grep(和egrep)中的基本用法,使大家对正则表达式有个整体的认识。
二、名词解释
正则表达式:
又称正规表示法、常规表示法(Regular Expression,代码中简写为regex、regexp或RE);
正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则(即模式)的字符串;
在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本;
许多程序设计语言都支持利用正则表达式进行字符串操作,如Perl、Python等;
元字符:
正则表达式中具有特殊意义的专用字符(类似于C语言中的关键字);
不表示字符本身的意义,而是用于额外的功能性描述;
三、分类
根据元字符数量和扩展功能,正则表达式一般分为“基本正则表达式”和“扩展正则表达式”;
grep内置“基本正则表达式”的功能,也可使用grep -E利用“扩展正则表达式”完成字符串匹配;
egrep内置“扩展正则表达式”的功能;
四、基本正则表达式(grep)
基本正则表达式的元字符:
字符匹配:
1 2 3 | .:任意单个字符 [ ]:指定范围内的任意单个字符 [^]:指定范围外的任意单个字符 |
其中[ ]中字符范围如下:
1 2 3 4 5 6 7 8 9 10 11 | [a-z]:匹配单个小写字母 [A-Z]:匹配单个大写字母 [0-9]:匹配单个数字 [[:upper:]]:匹配单个大写字母 [[:lower:]]:匹配单个小写字母 [[:alpha:]]:匹配单个字母(不分大小写) [[:digit:]]:匹配单个数字 [[:alnum:]]:匹配单个字母或数字 [[:space:]]:匹配单个空白(包括空格,tab等) [[:punct:]]:匹配单个标点符号 [^]:指定范围外的任意单个字符 |
次数匹配:用来指定匹配其前面字符的次数
1 2 3 4 5 6 | *:任意次(.*匹配任意长度的任意字符) \?:0次或1次 \{m\}:匹配m次 \{m,n\}:匹配m~n次 \{m,\}:匹配至少m次 \{0,n\}:匹配至多n次 |
位置锚定:用于指定字符出现的位置
1 2 3 4 | ^:锚定行首 $:锚定行尾(^$表示空白行) \<:锚定词首,也可表示为\b \>:锚定词尾,也可表示为\b |
分组:又可称为子模式
1 | \( \):如\(ab\)*xy |
引用:
1 | \1:后向引用,引用前面的第一个左括号以及与之对应的右括号中的模式所匹配到的内容 |
五、扩展正则表达式(egrep)
“扩展正则表达式”较之“基本正则表达式”,元字符更加精简,不再需要反斜杠(\)转义,且增加了+,|等元字符,如下:
字符匹配:
1 2 3 | .:任意单个字符 [ ]:指定范围内的任意单个字符 [^]:指定范围外的任意单个字符 |
次数匹配:
1 2 3 4 5 6 7 | *:匹配前面的字符任意次 ?:匹配0或1次 +:匹配至少1次(新增) {m}:匹配m次 {m,n}:匹配m~n次 {m,}:匹配至少m次 {0,n}:匹配至多n次 |
位置锚定:
1 2 3 4 | ^:行首 $:行尾 \<,\b:词首 \>,\b:词尾 |
分组:
1 2 | ( ):分组 |:或 (新增) |
引用:
1 | \1:后向引用,引用前面的第一个左括号以及与之对应的右括号中的模式所匹配到的内容 |
六、实例
Question1:
显示/etc/rc.d/rc.sysinit文件中以#开头,后面跟至少一个空白字符,而后又有至少一个非空白字符的行
Answer1:
1 | grep "^#[[:space:]]\{1,\}[^[:space:]]\{1,\}" /etc/rc .d /rc .sysinit |
Question2:
显示/boot/grub/grub.conf中以至少一个空白字符开头的行
Answer2:
1 | grep "^[[:space:]]\{1,\}[^[:space:]]\{1,\}" /boot/grub/grub .conf |
Question3:
找出ifconfig命令结果中的1到255之间的整数
Answer3:
1 | ifconfig | egrep "\b([1-9][0-9]?|1[0-9]{2}|2[0-4][0-9]|25[0-5])\b" |
Question4:
显示/etc/passwd中用户名和备注内容一致的行
Answer4:
1 | egrep "([[:alnum:]]+):.*:\1:" /etc/passwd |
七、高级功能
非获取匹配:
正则表达式中,可以在子模式内部前面加“?:”来表示这个子模式只是一个“非获取匹配”;
“非获取匹配”不会被保存,不能在后向引用中获取;
如(?:[[:digit:]]+) ([[:alpha:]]+) \1可以匹配 555 abc abc,却不能匹配 555 abc 555;
正向预查:
正则表达式中,可以在子模式内部前面加“?=”来表示:首先,要匹配的文本必须满足子模式前面的表达式;其次,此子模式不参与匹配;
类似于自定义的位于文本末的字符边界\>;
如 Windows (?=[[:digit:]]+\b)匹配结果是 Windows 95 和 Windows 98 中的Windows字段,后面的数字只是作为匹配的依据而已;
反向预查:
与正向预查匹配方向相反,可以在子模式内部前面加“?<=”来表示:首先,要匹配的文本必须满足子模式后面的表达式;其次,此子模式不参与匹配;
类似于自定义的位于文本首的字符边界\<;
如 (?<=CNY: )[[:digit:]]+\.[[:digit:]]+ 可以匹配CNY: 128.04和CNY: 23.78 中数字字段,前面的CNY:字段只是作为匹配的依据而已;
八、补充
fgrep:(fast grep)不解析正则表达式,只能对固定的字符串进行搜索,故速度较grep和egrep快
九、参考资料
《Regular Expression Cookbook》