我不确定我是否没有完全理解grep
,或者正则表达式是否是导致我问题的根源,所以我有两个问题。我有一个名为test.txt
以下内容的简单测试文件:
$ cat test.txt Settings.xml blah Settings_1.xml blah Settings_2.xml
当我grep
在仅包含上述测试文件的目录中运行以下命令时,它返回没有匹配项:
$ grep -ir "Settings*xml"
1)为什么通配符*
没有捕捉到句点?
当我grep
这样运行时:
$ grep -ir "Settings*.xml"
唯一的区别是通配符后的句点,结果是:
test.txt:Settings.xml
2)为什么grep
找不到另外两个匹配项?
答案1
原因是*
在正则表达式中 是一个特殊字符,表示
zero or more preceding characters
。您必须转义*
才能表示文字*
字符\
。因此在您的示例中:
grep -ir "Settings*xml"
会搜索以 开头Setting
,结尾为零个或多个s
字符 和的字符串xml
。您的文件中没有这样的字符串,因为xml
前面总是.
。而这个:
grep -ir "Settings*.xml"
Setting
将搜索以 开头,然后在零个或多个字母之后有零个或多个s
和的字符串。.xml
s
您的第一个正则表达式将匹配如下内容:
Settingssxml
答案2
其他答案解释了发生了什么,回答了你的明确问题。我的回答旨在介绍更广泛的背景。
我猜你期望*
匹配零个或多个字符(任何字符)并且.
字面意思是.
。这适用于 shell 通配符,即如果你有文件像这样:
$ ls -1
Settings.xml
blah
Settings_1.xml
Settings_2.xml
然后(比如说,在bash
)你可以这样做:
$ echo Settings*.xml
Settings.xml Settings_1.xml Settings_2.xml
您没有得到预期的结果,因为grep
使用了正则表达式语法:
.
匹配(几乎)任何字符,*
表示“零个或多个前面的字符”,\
强制按字面意思解释下一个字符。
这就是为什么你应该"Settings*.xml"
使用"Settings.*\.xml"
。 在这种情况下:
.*
按照你的想法*
去做,\.
按照您的想法.
去做。