【问题标题】:Replace patterns that are inside delimiters using a regular expression call使用正则表达式调用替换分隔符内的模式
【发布时间】:2008-10-07 23:13:46
【问题描述】:

我需要剪掉所有出现在长字符串中的 inside 单引号的模式 '--'(保留单引号外的那些)。

有没有一种 RegEx 方法可以做到这一点? (将它与语言中的迭代器一起使用是可以的)。

例如,以

开头
"xxxx rt / $ 'dfdf--fggh-dfgdfg' ghgh- dddd -- 'dfdf' ghh-g '--ggh--' vcbcvb"

我最终应该得到:

"xxxx rt / $ 'dfdffggh-dfgdfg' ghgh- dddd -- 'dfdf' ghh-g 'ggh' vcbcvb"

所以我正在寻找可以从以下语言运行的正则表达式,如图所示:

    +-------------+------------------------------------------+
    |  Language   |                  RegEx                   |
    +-------------+------------------------------------------+
    | JavaScript  |  input.replace(/someregex/g, "")         |
    | PHP         |  preg_replace('/someregex/', "", input)  |
    | Python      |  re.sub(r'someregex', "", input)         |  
    | Ruby        |  input.gsub(/someregex/, "")             |
    +-------------+------------------------------------------+

【问题讨论】:

    标签: regex


    【解决方案1】:

    我从 Greg HewgillQn138522的回答中找到了另一种方法
    它基于使用这个正则表达式(适应包含我正在寻找的模式):

    --(?=[^\']*'([^']|'[^']*')*$)
    

    格雷格解释道:

    "它的作用是使用非捕获匹配 (?=...) 来检查字符 x 是否在带引号的字符串中。它会查找一些非引号字符直到下一个引号,然后查找单个字符的序列或引用的字符组,直到字符串的末尾。这取决于您的假设,即引号始终是平衡的。这也不是很有效。"

    用法示例如下:

    • JavaScript:input.replace(/--(?=[^']*'([^']|'[^']*')*$)/g, "")
    • PHP:preg_replace('/--(?=[^\']*'([^']|'[^']*')*$)/', "", input)
    • 蟒蛇:re.sub(r'--(?=[^\']*'([^']|'[^']*')*$)', "", input)
    • 鲁比:input.gsub(/--(?=[^\']*'([^']|'[^']*')*$)/, "")

    我已经针对 Ruby 进行了测试,它提供了所需的结果。

    【讨论】:

      【解决方案2】:

      这不能用正则表达式来完成,因为你需要维护你是在单引号内还是在外的状态,而正则表达式本质上是无状态的。 (另外,据我了解,可以在不终止“内部”区域的情况下转义单引号)。

      您最好的办法是逐个字符地遍历字符串,保留一个布尔标志来判断您是否在带引号的区域内 - 并以这种方式删除 -- 。

      【讨论】:

        【解决方案3】:

        如果允许稍微改变规则,这可能会起作用:

        import re
        p = re.compile(r"((?:^[^']*')?[^']*?(?:'[^']*'[^']*?)*?)(-{2,})")
        txt = "xxxx rt / $ 'dfdf--fggh-dfgdfg' ghgh- dddd -- 'dfdf' ghh-g '--ggh--' vcbcvb"
        print re.sub(p, r'\1-', txt)
        

        输出:

        xxxx rt / $ 'dfdf-fggh-dfgdfg' ghgh- dddd -- 'dfdf' ghh-g '-ggh-' vcbcvb
        

        正则表达式:

        (               # Group 1
          (?:^[^']*')?  # Start of string, up till the first single quote
          [^']*?        # Inside the single quotes, as few characters as possible
          (?:
            '[^']*'     # No double dashes inside theses single quotes, jump to the next.
            [^']*?
          )*?           # as few as possible
        )
        (-{2,})         # The dashes themselves (Group 2)
        

        如果开始和结束的分隔符不同,您可以使用以下内容:

        -{2,}(?=[^'`]*`)
        

        编辑: 我意识到如果字符串不包含任何引号,它将匹配字符串中的所有双破折号。解决它的一种方法是更改​​

        (?:^[^']*')?
        

        一开始就

        (?:^[^']*'|(?!^))
        

        更新正则表达式:

        ((?:^[^']*'|(?!^))[^']*?(?:'[^']*'[^']*?)*?)(-{2,})
        

        【讨论】:

          【解决方案4】:

          嗯。如果没有带引号的撇号,可能在 Python 中有一种方法,因为存在 (?(id/name)yes-pattern em>|no-pattern) 在正则表达式中构造,但目前它超出了我的想象。

          这有帮助吗?

          def remove_double_dashes_in_apostrophes(text):
              return "'".join(
              part.replace("--", "") if (ix&1) else part
              for ix, part in enumerate(text.split("'")))
          

          似乎对我有用。它的作用是将输入文本拆分为撇号上的部分,并仅在部分为奇数时替换“--”(即部分之前有奇数个撇号)。关于“奇数”的注意事项:零件编号从零开始!

          【讨论】:

            【解决方案5】:

            我相信您可以使用以下 sed 脚本:

            :again
            s/'\(.*\)--\(.*\)'/'\1\2'/g
            t again
            

            将其存储在一个文件 (rmdashdash.sed) 中,并在您的脚本语言中执行任何 exec 魔术,以便您执行以下 shell 等效项:

            sed -f rmdotdot.sed 包含您的输入数据的文件

            脚本的作用是:

            :again

            s/'\(.*\)--\(.*\)'/'\1\2'/g

            替换模式 ' 后跟任何东西,然后是 -- 后跟任何东西,然后是 ',只是引号中的两个任何东西。

            t again

            请注意,此脚本会将 '----' 转换为 '',因为它是引号内的两个 -- 的序列。但是,'---' 会被转换成 '-'。

            没有像老学校那样的学校。

            【讨论】:

            • "foo 'bar' -- 'baz'" -> "foo 'bar' 'baz'"
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-02-12
            • 1970-01-01
            • 2013-01-04
            • 1970-01-01
            • 2017-07-24
            • 1970-01-01
            • 2014-03-29
            相关资源
            最近更新 更多