Regex 如何将正则表达式中的方括号与grep匹配?
我尝试将Regex 如何将正则表达式中的方括号与grep匹配?,regex,bash,grep,Regex,Bash,Grep,我尝试将[和]与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 "[
[
和]
与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
注:我已经试过了这篇文章中的所有答案,但在这个特殊的案例中都不起作用。我需要使用[]
中的括号,根据:
在大多数正则表达式中,字符类中唯一的特殊字符或元字符是右括号(])、反斜杠(\)、插入符号(^)和连字符(-)。通常的元字符是字符类中的普通字符,不需要反斜杠转义。
。。。而且
结束括号(])、插入符号(^)和连字符(-)可以通过使用反斜杠转义来包含,或者通过将它们放置在不具有特殊含义的位置来包含。
因此,假设grep
所支持的正则表达式语法的特殊风格符合这一点,那么我会认为“[a-z[\]]\+”
应该可以工作
但是,我的grep版本(GNU grep 2.14)仅与此正则表达式的“fdsl[]”
末尾的“[]”
匹配
但是,我尝试使用该引文中提到的另一种技术(将]
放在字符类中无法呈现其正常含义的位置,它似乎起到了作用:
$ echo "fdsl[]" | grep -o "[][a-z ]\+"
fdsl[]
根据POSIX正则表达式规范的章节:
']'
)出现在列表中的第一个位置(在首个扬抑符('^'
)之后,如果有),则右括号(']'
)将失去其特殊意义,并在括号表达式中表示。否则,除非它出现在排序符号中(如“[.].”“
)或是排序符号、等价类或字符类的右括号结尾。特殊字符'.
、'*'
、'['
和'\'.
(分别为句号、星号、左括号和反斜杠)在括号表达式中将失去其特殊含义'-'
和']'
,则应将']'
放在括号表达式中的第一位(在'^'
之后,如果有)和最后一位echo "fdsl[]" | grep -Eo "[][ a-z]+"
请注意E
标志,该标志指定使用ERE,该标志支持+
量词。+
量词在BRE(默认模式)中不受支持
Mike Holt的答案“[[a-z]\+”
中使用转义+
的解决方案之所以有效,是因为它运行在GNU grep上,这实际上是(这意味着实现可以给出有意义的行为并对其进行记录,或者抛出语法错误,或者其他)
如果您认为您的代码只能在GNU环境下运行,那么使用Mike Holt的答案就完全可以了。以sed
为例,您在使用(没有切换到ERE的标志)时会遇到BRE问题,而且使用POSIX BRE编写甚至是简单的正则表达式都很麻烦,因为POSIX BRE中唯一定义的量词是*
原始正则表达式
请注意,grep
逐行使用输入文件,然后检查该行是否与正则表达式匹配。因此,即使对原始正则表达式使用p
标志,\n
始终是多余的,因为正则表达式无法跨行匹配
虽然有可能,但我认为在这个任务中使用p
标志更为自然
鉴于这一投入:
$ echo -e "fds\tl[]kSAJD<>?,./:\";'{}|[]\\!@#$%^&*()_+-=~\`89"
fds l[]kSAJD<>?,./:";'{}|[]\!@#$%^&*()_+-=~`89
尽管我们可以删除\n
(因为它是多余的,如上所述),以及一些其他不必要的转义:
$ echo -e "fds\tl[]kSAJD<>?,./:\";'{}|[]\\!@#$%^&*()_+-=~\`89" | grep -Po "[ \[\]\ta-zA-Z/:.0-9_~\"'+,;*=()$\!@#&?-]+"
fds l[]kSAJD
?,./:";'
[]
!@#$
&*()_+-=~
89
$echo-e“fds\tl[]kSAJD?,./:\”;{}}}[\]\!@$%^&*()
fds l[]kSAJD
?,./:";'
[]
!@#$
&*()_+-=~
89
一个问题是[
是表达式中的一个特殊字符,它不能用\
进行转义(至少在我的grep版本中不是这样)。解决方法是像[[[]那样定义它。fdsl\[\]
怎么样?你的]
是@Joe的不可替代的复制品:不是真正的复制品,因为它必须处理bash的问题quirks@Joe,这两种解决方案对我都不起作用..我不确定为什么“[[a-z]\+“
有效-它很可能是一个不可移植的扩展,因为我在规范@Jahid Yes中找不到任何关于它的信息。我在sed
@Jahid中经常使用\+
:如果您使用的是GNU工具,\+
,\{1,\}”
和\?
作为BRE的扩展受到支持。根据POSIX规范,只有*
是BRE的官方部分。@Jahid我不会说\+
有争议,因为它可能没有那么便携,而且显然不符合POSIX。如果您在某个版本的Linux上使用GNU grep,并且您不关心可移植性,y你使用\+
可能是安全的。手册页明确指出,非元字符可以通过反斜杠转义变成元字符。因此,这不是一些未记录的功能。应该注意的是,我并不反对NHAHDH所说的任何话,事实上,我认为他的答案是更好的答案。我们只是一个从不同的角度来研究这个问题。他在POSIX上下文中构建了它,我很高兴地假设它是GNU/Linux上下文。GNU grep将在BRE模式下使用\+
等同于在ERE模式下使用+
,但我同意如果需要(如果不是出于可移植性以外的原因)使用ERE会更好@ChronoKitsune:谢谢你的提示,我找到了GNU文档:是的,$ echo -e "fds\tl[]kSAJD<>?,./:\";'{}|[]\\!@#$%^&*()_+-=~\`89" | grep -Po "[ \[\]\ta-zA-Z/:.0-9_~\"'+,;*=()$\!@#&?-]+"
fds l[]kSAJD
?,./:";'
[]
!@#$
&*()_+-=~
89