第3章 查找与替换——(POSIX)BRE正则表达式

1.grep的用法:
-E 使用扩展正则表达式进行匹配。
-F 使用固定字符串进行匹配,可省略
-e 字符串以减号开头时grep会混淆。-e可以指定其参数为模式(字符串)
-f pat-file 从pat-file文件读取模式作匹配
-i 模式匹配时忽略字母大小写差异
-l 列出匹配模式的文件名称,而不是对应的行
-q 静默的。grep成功则离开,而不是写入stdin。
-s 不显示错误信息。通常与-q并用。
-v 取反,显示不匹配的行
2.(POSIX)正则表达式
(1)特殊字符常称为元字符(meta字符)
(2)POSIX BRE与ERE的meta字符



(3)方括号表达式:
1》字符集 [::]括起来,如英文字符[[:alpha:]]
2》排序符号 [..]括起来 如[[.ch.]],匹配ch,而不匹配单个c或h
3》等价字符集 [==]括起来 如[[=e=]],在法文locale里,可能匹配于e、é、è等
注意:以上三种构造必须在方括号表达式中

3.基本正则表达式(BRE)
(1)匹配单个字符
1》如何让meta字符表示他们自己?
答:前面加上反斜杠\转义:如\*匹配*,\\匹配\
2》. 匹配“任一字符”。
3》用方括号表达式可以匹配单个字符
注意一:在方括号表达式里,^放在字首表示取反,也就是匹配不在方括号列表里的任意字符。如[^aeiou]匹配除小写元音以外的字符。
注意二:方括号表达式允许“范围”,如[0-9]表示0123456789、[0-9a-z]等
这里有个问题:这样做可能降低移植性,因为这里的范围与locale相关(locale排序序列里的位置,你系统上的[0-a]和他系统上的[0-a]可能包括不一样的字符)
4》方括号表达式的注意点:
<1>在方括号表达式中,其他的meta字符都会失去特殊含义。
<2>如何让]进入该集合?
答:将]放到列表的最前面
如何让-进入该集合?
答:将-放到列表的最前面
如何让]和-都进入该集合?
答:将]放到第一个字符,将-放到最后一个字符
(2)后向引用
第一步:将子表达式包围在\(与\)里。可嵌套。
第二步:在同一模式之后使用\digit。digit范围1——9。、
意义:指的是“匹配于第n个先前方括号内子表达式匹配成功的字符”
如何确定子表达式的编号,以左括号为准,从左至右依次为1——9
例:\(['"]\).*\1 匹配以单引号或双引号括起来的字。当前面匹配成功的是’时,后面必须出现’才算匹配。前面是”时,同。
(3)*和\{ \}
*:表示前面的正则表达式重复出现任意次(包括0次)
如ab*c匹配:ac abc abbc 但是不匹配aQc
注意:在BRE中,*在最前面表示其本身,失去特殊意义
\{和\}:
1》\{n\} 前置正则表达式所得结果出现n次
2》\{n,\} 前置正则表达式所得结果至少出现n次
3》\{n,m\} 前置正则表达式所得结果出现次数>=n次,<=m次
n与m的值必须介于0至RE_DUP_MAX(含)之间。
RE_DUP_MAX:POSIX定义的符号常量,可用getconf取得。
注意:以上两个meta符只能作用于单个字符正则表达式
(4)文本匹配描点
^和$称为描点
^ 表示其后的正则表达式出现在行开头
$ 表示其后的正则表达式出现在行结束
如^$表示空行
注意:^和$只有在BRE的起始和结尾处才有特殊用途。
(5)BRE运算符优先级:

关于linux的参数执行顺序。。

        今天在看正则表达式的时候遇到了两个问题,用vi打开/etc下的sysctl.conf的时候会发现有许多空白行和注释行。但是有时候stdout的时 候并不需要这些信息,若是打印时则更能节省纸张资源。-_-!于是我用grep命令将其去除,具体指令为grep -v ‘^$’ /etc/sysctl.conf|grep -v ‘^#’可是运行完该句之后的结果着实让我头疼,因为我发现注释行仍然出现了,而且前面还多了一个数字。往上一检查才发现自己多打了一个n。。命令变成了 grep -vn ‘^$’ /etc/sysctl.conf|grep -v ‘^#’。
        这对我来说是个不错的收获。因为大家都知道管道命令会把前者的stdout转换为后者的stdin,而碰巧的是n正好有是grep的一个参数,用于输出行 号。于是后者的stdin的每行的开始都有了行号。这样每行的开始都不是#字符了,注释也就自然没被去除。看来管理时真的要小心谨慎,一不小心结果就会发 生错误。另外,如果有些童鞋在不是自己的主机上执行该命令的时候会发现命令完全正确,可是结果还是有类似错误。这时候很可能是因为grep被该用户 alias过的原因。比如该用户alias grep=’grep -v’.这样会有更奇怪的结果哦(会有两列行号^_^)当然这点如果多执行命令的话也是可以发现的,其实type grep一下就·ok。而且一般人不会这么做,毕竟v用于显示没有指定字符串的行。如果真是这个原因,怎么改呢?很简单,去改下用户目录下 的.bashrc文件吧。这个是login shell会读取的文件。里面会初始化一些命令别名,然后会注册一些环境变量。login时会被~/.bash_profile调用。如果发现grep被 alias成带v参数,就赶紧把它注释掉吧。要想立刻生效的话,手动读取一下吧。source ~/.bashrc 这样就ok了。
这时候,,又想到一个问题,上述命令中的参数v和n是哪个先执行呢。联系到最近在win32汇编上学的c调用、stdcall都是右边参数先入栈来看的 话,我想linux应该也类似吧(。。。纯属个人胡扯~~~~)。那样应该是自左向右顺序执行的。从结果来看,空行确实被去除了,那是不是真的是自左向右 的顺序呢。于是验证了一下。grep -nv ‘^$’ /etc/sysctl.conf|grep -v ‘^#’结果空行还是被去除了。看来假设不对。如果自左向右,那么-n执行后每行都有行号,再执行-v不会去除空行。当然这里有个问题,那就是我不清楚第 一个参数执行后是否真正影响了输出,如果行号没被算进去的话执行-v后还是会去除空行的。这样参数执行顺序的问题还是不敢下定论。。可是大年夜的没有网络 可用。看来有机会得去百度一下了。。
不过,这时候,,,天亮了。。下午四五点起床的孩子通宵无压力。。O~睡觉去了。。。
以上分析纯属本人臆测,OS为Cent OS。内核为2.6.32-71.e16.i686。不过我开了下gentoo,发现gentoo的用户~目录下好像没有.bashrc文件、、、
(以上均为本人学习过程中的杂乱思绪,不免大量错误,不做任何参考。。)

2012.1.23