我有一些关于 的问题grep
。
为什么下面的命令会匹配'
<Hello
'?$ grep -E "\<H" test Hello World <Hello H<ello
需要做什么才能只匹配'
<Hello
'?
答案1
要防止grep
特殊解释字符串(正则表达式),请使用-F
(或--fixed-string
):
$ cat test
one < two
Hello World
X<H
A <H A
I said: <Hello>
$ grep -F '<H' test
X<H
A <H A
I said: <Hello>
请记住正确引用搜索模式,否则您的 shell 可能会错误地解释它。例如,如果您grep -F <H test
改为运行,shell 将尝试打开名为“H”的文件并使用它来提供grep
.grep
将在该流中搜索字符串“test”。以下命令大致彼此等效,但与上面的命令不同:
grep -F <H test
grep -F test <H # location of `<H` does not matter
grep -F H test
cat H | grep -F test # useless cat award
至于仅匹配单词,请查看手册页grep(1)
:
-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 constituent 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.
使用示例(使用上面的测试文件):
$ grep -F -w '<H' test
A <H A
(-F
此处是可选的,因为<H
没有特殊含义,但如果您打算扩展此文字模式,那么它可能会很有用)
要匹配单词的开头,您确实需要正则表达式:
$ grep -w '<H.*' test # match words starting with `<H` followed by anything
A <H A
I said: <Hello>
答案2
<
不是任何 grep 中的特殊字符。然而,在 GNU grep 中\<
是特殊的,意味着单词的开头Hello
(因此所有输入行之前的零宽度边界)。
在所有grep
s中\
都是特别的。它可以转义特殊字符以删除其特殊含义(因此它按字面匹配)或为字符添加特殊含义(通常用于在不破坏现有脚本的情况下引入新运算符,另一种方法是使用否则无效的内容如*?
或(?
) 或 ANSI C 转义序列,如\n
, \t
...
要删除 的特殊含义\
,就像其他含义一样,您需要另一个\
.
因此,要匹配<Hello
,您需要:
grep -E '<Hello'
为了匹配\<Hello
,您需要:
grep -E '\\<Hello'
注意<
和\
都是特殊的到外壳也需要引用对于外壳同样,因此上面的单引号 (\
对于 shell 而言在双引号内也是特殊的,尽管仅在引号内的其他特殊字符(如换行符、双引号、反斜杠、美元或反引号)前面,所以您需要grep -E "\\\<Hello"
或grep -E "\\\\<Hello"
匹配\<Hello
)。
为了使该模式匹配整行,请将-x
选项添加到 grep:
grep -xE '<Hello'
只会匹配其内容完全一致的行"<Hello"
。
要在行的开头匹配:
grep -E '^<Hello'
(将匹配"<Hello"
和"<Hello world>"
,但不匹配World <Hello
.
匹配<Hello
前面没有非空白字符(我对你的解释在单词的开头):
grep -E '(^|[[:blank:]])<Hello'
或使用 BRE:
grep '^\(.*[[:blank:]]\)\{0,1\}<Hello'