怪异的grep结果
2011-12-20 16:00 Jeff 阅读(771) 评论(0) 编辑 收藏 举报
原意是发现文件中IP地址为1.1.1.1的行(不需显示1.1.1.191这样的).但是写错了,忘记"."是用于匹配任意字符的.但却发现有几条grep结果很奇怪.
根据GNU Grep的manual
"<" Match the empty string at the beginning of word
">" Match the empty string at the end of word
所以当时我就写成了grep "<1.1.1.1>" 结果如下:
ksim@MxGms3:~> echo "1.1.1.1 games1"|grep "<1.1.1.1>"
1.1.1.1 games1
ksim@MxGms3:~> echo "1.1.1.191 games1"|grep "<1.1.1.1>"
1.1.1.191 games1
第二句执行结果,出乎我的意料.经人提醒,这里"."匹配了任意字符.
于是我改成 grep "<1.1.1.1>"
执行结果如下:
ksim@MxGms3:~> echo "1.1.1.191 games1"|grep "<1.1.1.1>"
ksim@MxGms3:~> echo "1.1.1.1 games1"|grep "<1.1.1.1>"
1.1.1.1 games1
后来,改成-w也可以: grep -w "1.1.1.1"
执行结果如下:
ksim@MxGms3:~> echo "1.1.1.191 games1"|grep -w "1.1.1.1"
ksim@MxGms3:~> echo "1.1.1.1 games1"|grep -w "1.1.1.1"
1.1.1.1 games1
但是我依然不明白最早使用命令的输出结果,就是这一句:
ksim@MxGms3:~> echo "1.1.1.191 games1"|grep "<1.1.1.1>"
1.1.1.191 games1
为什么会把1.1.1.191显示出来., "."是用于代表一个任意字符的,但只是代表一个任意字符,不能代表多个,这个怎么能匹配出来1.1.1.191. 同样的,我改成-w option,也是不理解:
ksim@MxGms3:~> echo "1.1.1.191 games1"|grep -w "1.1.1.1"
1.1.1.191 games1
但这又应该和"." 操作符有关的,因为我又试了以下命令:
ksim@MxGms3:~> echo "121212121 games1"|grep "<1212121>"
ksim@MxGms3:~> echo "1212121 games1"|grep "<1212121>"
1212121 games1
把"."换成2,就不会把121212121显示出来.
所以所有的问题归结到一个问题, 那就是"<1.1.1.1>" 和 -w "1.1.1.1"
这2个难道不是精确匹配" 4个1以及4个1中间夹带3个任意字符" ??
问题出在哪里?
查看GNU manul,可以看到下面一段:
-w, --word-regexp
Select only those lines containing matches that form whole words. The test is that the matching substring must either be at the beginning of the line, or preceded by a non-word con-stituent character. Similarly, it must be either at the end of the line or followed by a non-word constituent character. Word-constituent characters are letters, digits, and the underscore.
也就是说-w只关心constituent characters, 像其他符号不影响匹配结果.比如:
ksim@MxGms3:~> echo "+abc++" |grep -w "abc"
+abc++
ksim@MxGms3:~> echo "+abc+abc+" |grep -w "abc"
+abc+abc+
ksim@MxGms3:~> echo "+ac+abc+" |grep -w "abc"
+ac+abc+
ksim@MxGms3:~> echo "+abc+ac+" |grep -w "abc"
+abc+ac+
而且发现"<" ">"的效果和-w一样:
ksim@MxGms3:~> echo "+abc+ac+" |grep ""
+abc+ac+
姑且认为两者是等价的吧.