【问题标题】:Replace each pattern in regexp替换正则表达式中的每个模式
【发布时间】:2016-01-22 09:52:46
【问题描述】:

我很难找到正确的模式来获得我想要的字符串。

我的起始字符串是:

,,,,C3:,D3,E3,F3,,

我想拥有

      C3:  [D3,E3,F3]
  1. 我想用双空格替换每个起始逗号
  2. 用双空格和左方括号替换冒号后的逗号
  3. 用右方括号替换尾随逗号

现在,我尝试了这个:

> a = ",,,,C3:,D3,E3,F3,,"
=> ",,,,C3:,D3,E3,F3,,"
> b = a.gsub(/^,*/, "  ").gsub(/(?<=:),/, "  [").gsub(/[,]*$/,"" ).gsub(/[ ]*$/, "]")
=> "  C3:  [D3,E3,F3]"
> b == "        C3:  [D3,E3,F3]"
=> false

在这种情况下,我无法将每个起始逗号替换为双空格以获得 8 个空格。

您能帮我找到正确的正则表达式吗?如果可能的话,请改进我的代码?

【问题讨论】:

标签: ruby-on-rails ruby regex gsub


【解决方案1】:

要将每个起始逗号替换为双空格,您需要使用\G 运算符,即.gsub(/\G,/, ' ')。该运算符告诉正则表达式引擎在字符串的开头进行匹配,然后在每次成功匹配后进行匹配。因此,您只需将字符串开头的每个连续逗号替换为 .gsub(/\G,/, ' ')

然后,您可以添加其他替换:

s.gsub(/\G,/, ' ').sub(/,+\z/, ']').sub(/:,+/, ': [')

IDEONE demo

s = ",,,,C3:,D3,E3,F3,,"
puts s.gsub(/\G,/, '  ').sub(/,+\z/, ']').sub(/:,+/, ':  [')

输出:

        C3:  [D3,E3,F3]

【讨论】:

  • 谢谢,我不知道\G模式。
  • 仅供参考,我还摆脱了您的一个正则表达式中的后视,后视是相当昂贵的正则表达式子模式。由于您知道上下文(它是:),您可以匹配它,然后轻松地重新插入替换模式。
  • 另一种选择是",,,hi".gsub(/^(,+)/, ' '*'\1'.size)。但是,我很困惑为什么没有捕获组:",,,hi".gsub(/^,+/, ' '*'\1'.size)。 (我在测试之前确实重新加载了 IRB。)
  • @CarySwoveland:它不像你想的那样工作:'\1'.size 始终是2,因为\1 被视为文字字符串。 puts '\1'.size 输出 2,它永远是 2。 Here is an example of how to use a "callback" with Ruby's gsub - 可以,但需要更多编码。
【解决方案2】:

要构造所需的字符串,需要知道:

  • 前导逗号的数量(由前导逗号组成的字符串的大小)
  • 前导逗号后面的字符串,直到并包括冒号
  • 冒号后面的逗号和两个或多个逗号之间的字符串

构造一个将这三个字符串中的每一个都保存到捕获组的正则表达式是一件简单的事情:

r = /
    (,*)   # match leading commas in capture group 1
    (.+:)  # match up and including colon in capture group 2
    ,      # match comma     
    (.+)   # match any number of any characters in capture group 3
    ,,     # match two commas
    /x     # extended/free-spacing regex definition mode

",,,,C3:,D3,E3,F3,," =~ r

我们现在可以从三个捕获组的内容中形成所需的字符串:

"#{'  '*$1.size}#{$2} [#{$3}]"
  #=> "       C3: [D3,E3,F3]"

【讨论】:

    猜你喜欢
    • 2016-10-20
    • 1970-01-01
    • 1970-01-01
    • 2012-02-12
    • 2013-01-10
    • 1970-01-01
    • 2017-08-08
    • 1970-01-01
    • 2023-03-22
    相关资源
    最近更新 更多