我正在尝试将[
和]
与grep匹配,但只能成功匹配[
。无论我如何尝试,我都似乎无法匹配]
。
这是一个代码示例:
echo "fdsl[]" | grep -o "[ a-z]\+" #this prints fdsl
echo "fdsl[]" | grep -o "[ \[a-z]\+" #this prints fdsl[
echo "fdsl[]" | grep -o "[ \]a-z]\+" #this prints nothing
echo "fdsl[]" | grep -o "[ \[\]a-z]\+" #this prints nothing
编辑:我需要这样做的原始正则表达式就是这个:
echo "fdsl[]" | grep -o "[ \[\]\t\na-zA-Z\/:\.0-9_~\"'+,;*\=()$\!@#&?-]\+"
#this prints nothing
N.B:我已经尝试了this帖子中的所有答案,但这并不适用于这个特殊情况。我需要在[]
内使用这些括号。
答案 0 :(得分:11)
根据POSIX正则表达式规范的BRE/ERE Bracketed Expression部分:
- [...]右括号(
醇>']'
)将失去其特殊含义,如果它首先出现在列表中(在最初的旋律之后('^'
),则表示自己在括号表达式中,如果有的话)。否则,它将终止括号表达式,除非它出现在整理符号(例如"[.].]"
)中,或者是整理符号,等价类或字符类的结束右括号。特殊字符'.'
,'*'
,'['
和'\'
(句点,星号,左括号和反斜杠)将在括号表达式中失去其特殊含义
和
- [...]如果括号表达式同时指定
醇>'-'
和']'
,']'
应首先放置('^'
之后,如果有的话)和'-'
最后在括号表达式中。
因此,你的正则表达式应该是:
echo "fdsl[]" | grep -Eo "[][ a-z]+"
请注意E
标志,该标志指定使用支持+
量词的ERE。 BRE(默认模式)不支持+
量词。
Mike Holt使用转义"[][a-z ]\+"
回答+
的解决方案有效,因为它在GNU grep上运行,extends the grammar to support \+
to mean repeat once or more。它实际上是undefined behavior according to POSIX standard(这意味着实现可以提供有意义的行为并记录它,或者抛出语法错误,或者其他)。
如果您认为您的代码只能在GNU环境中运行,那么使用Mike Holt的答案就完全没问题了。以sed
为例,当您使用POSIX sed
(没有标志切换到ERE)时,您会被BRE困住,并且使用POSIX BRE编写简单的正则表达式很麻烦,其中唯一定义的量词是*
。
请注意,grep
逐行使用输入文件,然后检查该行是否与正则表达式匹配。因此,即使您在原始正则表达式中使用P
标记,\n
仍然是多余的,因为正则表达式不能跨行匹配。
虽然可以match horizontal tab without P
flag,但我认为使用P
标志执行此任务更为自然。
鉴于此输入:
$ echo -e "fds\tl[]kSAJD<>?,./:\";'{}|[]\\!@#$%^&*()_+-=~\`89"
fds l[]kSAJD<>?,./:";'{}|[]\!@#$%^&*()_+-=~`89
问题中的原始正则表达式稍作修改(最后是unescape +
):
$ echo -e "fds\tl[]kSAJD<>?,./:\";'{}|[]\\!@#$%^&*()_+-=~\`89" | grep -Po "[ \[\]\t\na-zA-Z\/:\.0-9_~\"'+,;*\=()$\!@#&?-]+"
fds l[]kSAJD
?,./:";'
[]
!@#$
&*()_+-=~
89
虽然我们可以删除\n
(因为它是多余的,如上所述),以及其他一些不必要的转义:
$ echo -e "fds\tl[]kSAJD<>?,./:\";'{}|[]\\!@#$%^&*()_+-=~\`89" | grep -Po "[ \[\]\ta-zA-Z/:.0-9_~\"'+,;*=()$\!@#&?-]+"
fds l[]kSAJD
?,./:";'
[]
!@#$
&*()_+-=~
89
答案 1 :(得分:6)
一个问题是[
是表达式中的特殊字符,并且无法使用\
进行转义(至少不是我的grep风格)。解决方案是将其定义为[[]
。
答案 2 :(得分:3)
在大多数正则表达式中,字符类中唯一的特殊字符或元字符是右括号(]),反斜杠(\),插入符号(^)和连字符( - )。通常的元字符是字符类中的普通字符,不需要用反斜杠转义。
......和......
结束括号(]),插入符号(^)和连字符( - )可以通过用反斜杠转义它们,或者将它们置于不具有其特殊含义的位置来包含。
因此,假设grep
支持的正则表达式语法的特定风格符合这一点,那么我原本期望"[ a-z[\]]\+"
应该有效。
但是,我的grep版本(GNU grep 2.14)只匹配"[]"
末尾的"fdsl[]"
和此正则表达式。
但是,我尝试使用该引用中提到的其他技术(将]
置于角色类中不能正常意义的位置,并且似乎有效:
$ echo "fdsl[]" | grep -o "[][a-z ]\+"
fdsl[]