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