我有一个包含以下内容的文件:
sh-4.2$ cat file1
example of multiple
pattern
this is an
example of multipole
sorry multiple
pattern matching
using grep
so the example is the
file itself
-example
-multiple
-bye
tata
!
在上述文件中搜索“-example”时,grep 命令没有给出所需的输出。我知道如果模式包含“-”,则应使用 -e 选项:
在第一个例子中我使用了-例子直接不带任何引号:
sh-4.2$ grep -example file1
example of multiple
example of multipole
so the example is the
-example
-例子带单引号:
sh-4.2$ grep '-example' file1
example of multiple
example of multipole
so the example is the
-example
-例子带双引号和转义字符
sh-4.2$ grep "\-example" file1
-example
sh-4.2$
答案1
好吧,您知道搜索模式包含“-”,并且您知道当搜索模式包含“-”时,您需要使用该-e
标志。由于您没有使用该-e
标志,因此 shell 会将您的“模式”解释为参数(和参数)。您可以通过以下方式查看:
$ grep "-foo" file1
grep: oo: No such file or directory
通过扩展,您的代码grep "-example" file1
告诉 shell 您想要grep
使用-e
参数和参数“xample”运行。
这与我们尝试类似的方法时遇到的问题相同rm -my-silly-file-name
- 它不起作用,我们需要使用类似的方法rm ./-my-silly-file-name
。另一种解决方法是rm -- -my-silly-file-name
.我们可以在这里使用这个习语:
$ grep -- "-example" < file1
-example
“--”告诉 shell 它后面的所有内容不是一个论点。
或者,您可以简单地用“\”转义“-”,如您所见:
grep "\-example" file1
本文详细介绍了引用的一些细节: 相关部分是应由 shell 解释的参数和反引号命令用双引号括起来。当您使用双引号时,内容由 shell 解释。
答案2
您“知道模式[以]'-'开头,则应使用-e选项”,但您在应该使用它时却没有使用它。grep -e -example file1
会给你预期的结果。
以下是每个示例中实际执行的内容:
grep -example file1
=>grep -e xample file1
(-e是必要的)grep '-example' file1
=>grep -e xample file1
(-e是必要的)grep "\-example" file1
=>grep \-example file1
(-e不是必需的)
答案3
以 开头的参数-
被视为一个选项。
在前两种情况下,传递给的第一个参数grep
是-example
,它grep
理解为-e xample
(选项xample
的参数-e
,因此搜索xample
)。
在第三种情况\-example
下传递给grep
.由于它不以 开头-
,因此不将其视为一个选项。它被视为正则表达式。然而,根据 POSIX 未指定 的行为\-
,因此您无法保证它匹配的内容。对于大多数grep
实现,\-
将匹配 a -
,但是您可以想象可能是特殊运算符grep
的实现\-
(例如,参见 GNUgrep
其中\+
是特殊运算符并且与文字不匹配+
)。
如果您-example
不想被视为一种选择,您需要:
grep -- -example file
。标志着--
选项的结束。它后面的任何内容都是非选项(因此第一个参数是要搜索的模式,其余是要查找的文件列表)。grep -e -example file
。这里,-example
被视为-e
选项的参数。
这就是为什么你应该习惯写作的原因:
grep -e "$pattern" file
或者
grep -- "$pattern" file
如果你不能保证$pattern
不会开始-
。
注意,这里你也可以这样写:
grep '[-]example' file
虽然看到括号表达式(不带范围)与 bash 中的意外字符匹配关于这种方法可能出现的并发症。