在使用" []"时获得特殊结果在egrep虽然" \"(转义序列)在Linux中使用

时间:2015-12-19 19:57:47

标签: regex grep

最近我在使用正则表达式做家务时遇到了以下情况。

s@ubuntu:~$ echo b | egrep []b]
b
s@ubuntu:~$ echo b | egrep [[b]
b
s@ubuntu:~$ echo b | egrep []b[]
b
s@ubuntu:~$ echo b | egrep [b[]
b
s@ubuntu:~$ echo b | egrep [[b]]
s@ubuntu:~$ echo b | egrep [b]]
s@ubuntu:~$ echo b | egrep [b\]]
s@ubuntu:~$ echo b | egrep [b\\]]
s@ubuntu:~$ echo b | egrep [\[b\]]

为什么我没有得到' b'最近5个案例?

2 个答案:

答案 0 :(得分:5)

  • egrep [[b]] - 查找b[后跟];没找到。
  • egrep [b]] - 查找b后跟];没找到。
  • egrep [b\]] - 查找b后跟];未找到。 shell省略了反斜杠,但egrep没有看到。
  • egrep [b\\]] - 查找b或反斜杠后跟];没找到。
  • egrep [\[b\]] - 查找b[后跟];未找到。 shell省略了反斜杠,但egrep没有看到。

在一个字符类(由[开始)中,第一个]终止该类,除非][之后的第一个字符,或第一个字符在[^之后为一个否定的字符类。请注意,]不是正则表达式元字符,除非前面有[使其成为字符类的末尾。您还发现$不是字符串中间的元字符,也不是^,除非它出现在开头,*也不+也不?如果它们首先出现,等等。请参阅POSIX Regular Expressions进行详细讨论 - egrep(现在grep -E)处理的正则表达式是“扩展正则表达式”。

egrep有机会看到它们之前,shell会出现反斜杠。您应该将正则表达式用单引号括起来,以避免shell改变egrep看到的内容。

您可以通过更改回显内容来演示我的分析:

echo '[b]' | egrep [[b]]
echo '[b]' | egrep [b]]
echo '[b]' | egrep [b\]]
echo '[b]' | egrep [b\\]]
echo '[b]' | egrep [\[b\]]

该输出是:

[b]
[b]
[b]
[b]
[b]

这些例子中的[(在回音数据中)出于美观的原因而存在;它可以省略,并且可以接受这些行。

答案 1 :(得分:3)

原因在于括号表达式中应用的特殊规则:

  

右侧方括号]必须在开场[[^后立即放置,以作为文字对待。

  

在字符集\

中逐字处理转义字符[...]

在成瘾中,shell会在将表达式传递给\之前应用转义字符egrep,因为正则表达式周围缺少单个'...'或双引号"..."

Jonathan Leffler用例子解释得很清楚,我只能在括号内报告Posix扩展规则的链接,以添加概述:

http://pubs.opengroup.org/onlinepubs/007904875/basedefs/xbd_chap09.html#tag_09_03_05

<强>更新

带引号的相同表达式:

# this matches 'b]' or '\]'
~$ echo b] | egrep '[b\]]'
b]
~$ echo '\]' | egrep '[b\]]' # note the quotes prior and after the pipe
\]

# the next one is equivalent to '[b\]]' 
# cause a double \ inside chars class is redundant
~$ echo b] | egrep '[b\\]]'
b]
~$ echo '\]' | egrep '[b\\]]'
\]

# the last one matches '\]' or '[]' or 'b]'
~$ echo b] | egrep '[\[b\]]'
[b]
~$ echo [] | egrep '[\[b\]]'
[]
~$ echo '\]' | egrep '[\[b\]]'
\]
# without quotes in the echo section, the escape \ is applied by the shell
# so egrep receive only a closing bracket ']' and nothing is printed out
~$ echo \] | egrep '[\[b\]]'

# If we remove instead the quotes from the egrep section 
# the regex becomes equivalent to [[b]] so it now matches '[]' or 'b]' and not '\]' anymore
~$ echo '\]' | egrep [\[b\]]
~$ echo '[]' | egrep [\[b\]]
[] 
~$ echo 'b]' | egrep [\[b\]]
b]