我的问题来源是答案在此链接上,加上一些额外的东西
更新
我理解第一个命令 iegrep \\[[a-z\|1-9]*\\] file
但我不理解第二个命令 ie 的输出grep \[[a-z\|1-9]*\] file
。
现在,我只想了解第二个命令的输出是如何构造的,特别是为什么 grep 完全选择了整个第三行和第四行,但只选择了第二行和第三行直到第一行]
答案1
这里有太多变量和未声明的假设,无法详尽地回答您的问题。
这里的主要陷阱是 shell(即大多数 Bourne 兼容的 shell - 实际上不确定 zsh 或 csh 及其衍生物)默认将通过未扩展的 glob如果它不匹配任何东西。因此,首先尝试使用像这样的表达式\\[[a-z0-9]*\\]
作为通配符。如果没有匹配的文件(比如\fno[rd\]
非字母都是文字的)通配符将grep
逐字传递。
(让我们再次检查一下。这是一个双反斜杠,即带引号的文字反斜杠后跟两个左方括号。第一个创建一个字符类,其第一个字符是第二个,文字[
。将其解析为正则表达式的结果有所不同,但同样令人费解。)
对此唯一明智的解决方案是正确引用任何不需要通过 shell 进行空格标记化和通配符扩展的内容。我的建议是在所有正则表达式周围使用单引号。然后,您将能够对匹配内容和方式形成合理的期望,而无需二对您的模式的专家解释(一个 shell,一个正则表达式)。
如果你想var[1]
完全匹配,正则表达式[a-z]*\[[0-9]*\]
可以做类似的事情。如果您希望方括号成为字符类的一部分,请尝试[][a-z0-9]*
其中第一个]
和第二个[
是字符类的文字成员。如果您将它们传递到grep
shell 中,请记住它们周围的单引号。
答案2
我们慢慢走吧。如果有一个包含以下内容的文件(仅一行,以便更容易显示):
$ cat infile
list[1]; i[ab1]; var[1] [1]var [1]var[2]
A
简单的grep --color a
会将所有 a 显示为红色。 (因为该网站确实允许控制颜色:假设粗体是红色):
$ grep --color a infile
list[1]; i[
Ab1]; v
Ar[1] [1]v
Ar [1]v
Ar[2]
如果 a 不带引号(如上所述)或带引号,则会发生完全相同的情况:
$ grep --color \a infile
list[1]; i[
Ab1]; v
Ar[1] [1]v
Ar [1]v
Ar[2]
$ grep --color "a" infile
list[1]; i[
Ab1]; v
Ar[1] [1]v
Ar [1]v
Ar[2]
$ grep --color 'a' infile
list[1]; i[
Ab1]; v
Ar[1] [1]v
Ar [1]v
Ar[2]
为什么?因为 a 是两个都:
- 对外壳来说并不特殊。
- shell 删除引号,并且 grep 接收
a
与第一个参数相同的内容。反斜杠引号、双引号或单引号。
]
如果我们想选择大括号]
(让我们从右大括号开始):
$ grep --color ] infile
list[1
]; i[ab1
]; var[1
][1
]var [1
]var[2
]
]
如果引用(任何引用)也会发生同样的情况。
在这种情况下,它]
对于 shell 来说是特殊的,但在没有匹配的左大括号的情况下则不然。
对于右大括号,事情变得更加复杂。所有这些都会引发错误:
grep --color [ infile
grep --color '[' infile
grep --color "[" infile
为什么?因为 grep 接收到的内容全部案件是单一的[
。
您可以通过这个简单的 echo 来了解 shell 的作用:
$ echo \[ "[" '['
[ [ [
shell 删除一级引用,所有值看起来都一样。
[
但是 grep 想要接收到的理解我们实际上正在搜索的字符[
是反斜杠引用的方括号 ( \[
)。这一切都会发生:
$ echo \\[ "\[" '\['
\[ \[ \[
grep 可以与其中任何一个一起使用:
$ grep --color \\[ infile
list
[1]; i
[ab1]; var
[1]
[1]var
[1]var
[2]
[[]
使用[[]
(只有一个字符的字符列表)将得到相同的结果(只要它被引用)。
$ grep --color '[[]' infile
list
[1]; i
[ab1]; var
[1]
[1]var
[1]var
[2]
Grep 需要准确接收[[]
才能正常工作。看起来似乎不需要引号:
$ echo \[\[\] "[[]" '[[]' [[]
[[] [[] [[] [[]
但如果你创建一个名为 的文件[
,这个想法就会被打破:
$ touch \[
$ echo \[\[\] "[[]" '[[]' [[]
[[] [[] [[] [
那是因为它[
对于 shell 来说是特殊的。对于 shell,它启动文件名通配模式。如果一个(或多个)文件与该模式匹配,则文件列表将被替换。
所以,这将正确工作:
$ grep --color '[[]' infile
list
[1]; i
[ab1]; var
[1]
[1]var
[1]var
[2]
而这个:grep --color '[]]' infile
将匹配右大括号。
[][]
匹配左方括号和在右方括号中,您需要特定的字符序列(当然,带引号)。
如果你尝试这样做:
$ grep --color '[[]]' infile
不会有比赛,根本没有。你需要这个才能让它正常工作:
$ grep --color '[][]' infile
list
[1
]; i
[ab1
]; var
[1
][
1
]var
[1
]var
[2
]
按照该特定顺序,右大括号必须是字符范围内的第一个字符。左大括号必须是字符列表中的最后一个字符。
[]a-z0-9[]
然后,您可以添加其他字符(但不能添加;
):
$ grep --color '[]a-z0-9[]' infile
列表[1];
我[ab1];
变量[1][1]变量
[1]变量[2]
然后,您可以添加|
范围中缺少的内容并进行您发布的链接的匹配。该链接中的正则表达式与此处不同,并且以非常不同的方式工作。它以匹配一个[
、其他一些字符开始,并以结束符结束]
。类似的东西(贪婪的本质*
占据了整条线):
$ grep --color '\[.*\]' infile
list
[1];我[ab1];变量[1] [1]变量[1]变量[2]
或者也类似这样:
$ grep --color '[[][a-c0-9]*[]]' infile
list
[1]; i
[ab1]; var
[1][1]
var
[1]var
[2]`