【问题标题】:Regex that considers characters outside the match考虑匹配之外的字符的正则表达式
【发布时间】:2014-10-20 07:05:15
【问题描述】:

我想知道是否可以创建一个考虑匹配之外字符的正则表达式。因此,例如,一个正则表达式在语义上意味着“匹配字符 'hel',但前提是后面跟着 'lo'。所以在字符串 hello 中,它会匹配 hel

我知道正则表达式的最简单定义只是询问“这个字符串是否被接受为匹配项”,在这种情况下,这种区别实际上没有任何意义。但是对于可以突出显示字符串匹配的部分(如 grep/egrep)或基于正则表达式进行替换的引擎(如 sed),它既有意义又可以说非常有用。

【问题讨论】:

    标签: regex replace sed grep substring


    【解决方案1】:

    正向前瞻将适合此要求:

    hel(?=lo)
    

    但是像 sedawk 这样的 unix 工具不支持环视。

    【讨论】:

    • 有趣的想法。看起来即使在不支持它的工具中也有效。例如,我最初的问题的动力是删除 Sublime Text 中的尾随空格,我尝试了 `\s(?=$),并且 find-and-replace 接受了它,但它也删除了换行符。据推测,如果支持积极的前瞻,这将不会发生。
    • 我相信 sublime 支持它,\s(?=$) 肯定会匹配行尾换行符。如果您想匹配空格但不在行尾,请使用:\s(?!$)
    【解决方案2】:

    你会想要一个positive lookahead:

    hel(?=lo)
    

    这是一个演示:http://regexr.com/39d02

    如果您需要在命令行上执行此操作,正如其他人所提到的,sedgrep 不支持正向前瞻。

    这里是一个使用perl的例子

    echo "hello world, hel world" | perl -ne 's/hel(?=lo)/HEL/g; print;'
    # HELlo world, hel world
    

    【讨论】:

      【解决方案3】:

      答案是肯定的,通过两种不同的机制。

      首先,您可以将lo 包含在与整个正则表达式匹配的字符串部分中,但也可以在您关心的hel 部分周围设置一个捕获组。这是sed 的简单演示,您会注意到它只找到一个匹配项:

      sed -n 's/\(hel\)lo/\1/p' <<<$'hell\nhello\nhelen'
      

      根据您的工具和目标,这可能就是您所需要的。

      其次,您可以使用 lookaround - 在这种情况下,肯定(因为您想确保 is 那里有东西)前瞻(因为您希望它在匹配之后)。 grep 的 GNU 实现有一个 -P 标志来启用 Perl5 兼容的正则表达式,所以如果您使用该版本,以下命令的输出与上述 sed 之一相同:

      grep -oP 'hel(?=lo)'  <<<$'hell\nhello\nhelen'
      

      请注意,OS X 的系统 grep 是 BSD,而不是 GNU。我通过 Homebrew 将 GNU 版本安装为 ggrep,以便我可以在需要时使用它,但不会无意中依赖它。

      【讨论】:

        【解决方案4】:

        您可以使用正则表达式环视。您可以在这里找到非常有趣的文档:

        http://www.regular-expressions.info/lookaround.html

        Lookahead 和lookbehind,统称为“lookaround”,是 零长度断言就像行的开始和结束一样,并且开始 和单词锚的结尾。这 不同之处在于环视实际上匹配字符,但随后 放弃匹配,只返回结果:匹配或不匹配。那 这就是为什么它们被称为“断言”。他们不消耗字符 字符串,但仅断言匹配是否可能。 Lookaround 允许您创建正则表达式 没有它们就不可能创造,否则会变得很啰嗦 没有他们。

        正负前瞻

        Negative lookahead 如果你想匹配不 其次是别的东西。 负前瞻提供了解决方案:q(?!u)。消极的 前瞻结构是一对括号,带有开头 括号后跟一个问号和一个感叹号。 在前瞻中,我们有一个简单的正则表达式 u。

        正向预测的工作原理相同。 q(?=u) 匹配一个 q 后跟一个 u,而不使 u 成为匹配项的一部分。积极的 前瞻结构是一对括号,带有开头 括号后跟问号和等号。

        因此,正如人们回答的那样,您可以使用积极的前瞻:

        hel(?=lo)
        

        与你的 cmets 相关,如果你想删除结尾空格,那么你可以使用这个正则表达式:

        \s+$
        

        Working demo

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-23
          • 1970-01-01
          • 2016-09-02
          • 2010-11-19
          • 1970-01-01
          • 2014-03-22
          相关资源
          最近更新 更多