【问题标题】:How to replace Perl-style regex with MatchData object如何用 MatchData 对象替换 Perl 风格的正则表达式
【发布时间】:2017-04-20 04:11:10
【问题描述】:

我正在使用带有正则表达式的gsub 方法:

@text.gsub(/(-\n)(\S+)\s/) { "#{$2}\n" }

输入数据示例:

"The wolverine is now es-
sentially absent from 
the southern end
of its European range."

应该返回:

"The wolverine is now essentially
absent from  
the southern end
of its European range."

该方法工作正常,但 rubocop 报告和冒犯:

避免使用 Perl 风格的反向引用。

任何想法如何使用MatchData 对象而不是$2 重写它?

【问题讨论】:

  • 也可以使用命名捕获(并将它们称为\k<>):.gsub(/-\n(?<rest>\S+)\s/, "\\k<rest>\n")
  • @mudasobwa:你的回答中有一个非常有趣的错误。我不明白这将取决于 gsub 历史记录。
  • @EricDuminil 发生这种情况是因为$1 包含最后一个匹配项,并且a = b 被评估为RTL。
  • @mudasobwa:不仅仅是a = bs = "123"; s[p "2"] = p "1" 输出 "2" 然后 "1"
  • @EricDuminil 好吧,确实如此。 ""[p 2] = p 1 打印 2 1 因为这是两个参数,传递给 String#[]=(index, value)。正则表达式在那个阶段没有被评估,它只是被声明了。 "#$1"插值,它确实是就地扩展的。

标签: ruby regex rubocop


【解决方案1】:

如果你想使用Regexp.last_match

@text.gsub(/(-\n)(\S+)\s/) { Regexp.last_match[2] + "\n" }

或:

@text.gsub(/-\n(\S+)\s/) { Regexp.last_match[1] + "\n" }

请注意,在涉及逻辑时应使用gsub 中的块。如果没有逻辑,将第二个参数设置为 "\\1\n"'\1' + "\n" 就可以了。

【讨论】:

  • 此解决方案也适用于在 case 语句中使用正则表达式时
【解决方案2】:

您可以使用不带块的反斜杠:

@text.gsub /(-\n)(\S+)\s/, "\\2\n"

另外,只使用一个组会更简洁一些,因为不需要上面的第一个:

@text.gsub /-\n(\S+)\s/, "\\1\n"

【讨论】:

    【解决方案3】:

    此解决方案考虑了换行符之前的错误空格以及结束句子或字符串的单词。它使用String#gsub 和一个块并且没有捕获组。

    代码

    R = /
        [[:alpha:]]\- # match a letter followed by a hyphen
        \s*\n         # match a newline possibly preceded by whitespace
        [[:alpha:]]+  # match one or more letters
        [.?!]?        # possibly match a sentence terminator
        \n?           # possibly match a newline 
        \s*           # match zero or more whitespaces
        /x            # free-spacing regex definition mode
    
    def remove_hyphens(str)
      str.gsub(R) { |s| s.gsub(/[\n\s-]/, '') << "\n" }
    end
    

    示例

    str =<<_       
    The wolverine is now es-
    sentially absent from
    the south-
    ern end of its
    European range.
    _
    
    puts remove_hyphens(str)
    The wolverine is now essentially
    absent from
    the southern
    end of its
    European range.
    
    puts remove_hyphens("now es-  \nsentially\nabsent")
    now essentially
    absent
    
    puts remove_hyphens("now es-\nsentially.\nabsent")
    now essentially.
    absent
    
    remove_hyphens("now es-\nsentially?\n")
      #=> "now essentially?\n" (no extra \n at end)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-26
      • 2017-08-28
      相关资源
      最近更新 更多