【问题标题】:Ruby regex - replace dots with spaces in the middle of textRuby regex - 用文本中间的空格替换点
【发布时间】:2016-10-13 15:44:22
【问题描述】:

我有一个长文本,我想用空格替换点,但只能在文本中间。 例如:

Domain:...................google.com

我需要这样:

Domain:                   google.com

我发现了这个用单个空格替换点的正则表达式:

str.gsub!(/(?<=:)\.+(?=[^\.])/, ' ')

但这还不够,因为它会产生:

Domain: google.com

我需要保留与点一样多的空格。 你会怎么解决呢?

【问题讨论】:

  • 我建议.gsub(/(?&lt;!^|\w)\.|\.(?!\w|$)/, ' '),不需要块。或使用块 - /\.{2,}/(并使用与以下答案相同的块)
  • @WiktorStribiżew 我考虑过这一点,但在我看来,正则表达式应尽可能精确,最多可以消除误报。非块版本将在点作为句子分隔符时失败,而后者在省略号时失败。

标签: ruby regex


【解决方案1】:

你快到了,你的正则表达式很好,只需使用 String#gsub 的块版本来计算替换匹配的长度:

▶ str = 'Domain:...................google.com'
#⇒ "Domain:...................google.com"
▶ str.gsub(/(?<=:)\.+(?=[^\.])/) { |m| ' ' * m.length }
#⇒ "Domain:                   google.com"

【讨论】:

  • 干得好!我已经在查看块版本文档了!非常感谢! :-)
【解决方案2】:

如果您需要在您描述的上下文中执行此操作(以 : 分隔的键/值,其中值是域名),您可以简单地使用:

> s='Domain:............www.google.com'
 => "Domain:............www.google.com" 
> s.gsub(/(?<=[:.])\./, ' ')
 => "Domain:            www.google.com"

因为域名不包含: 或连续的点。

对于更一般的用途,请参阅@mudasobwa 答案,或者您也可以这样做:

s.gsub(/(?:\G(?!\A)|\A[^:]*:\K)\./, ' ')

(其中\G锚匹配上一次匹配后的位置,强制下一个结果是连续的)。

【讨论】:

    【解决方案3】:

    如果句点前面或后面有句点,听起来您希望用空格替换句点,并且我假设一串句点之前不一定有冒号。如果是这样,这里有两种方法可以做到这一点。

    str = "Domain:...................google.com"
    

    使用Enumerable#each_cons 代替正则表达式

    " #{str} ".each_char.each_cons(3).map { |before,ch,after|
      ch=='.' && (before=='.' || after== '.') ? ' ' : ch }.join
      #=> "Domain:                   google.com"
    

    步骤如下。

    s = " #{str} "
      #=> " Domain:...................google.com " 
    a = s.each_char
      #=> #<Enumerator: " Domain:...................google.com ":each_char> 
    e = a.each_cons(3)
      #=> #<Enumerator: #<Enumerator: " Domain:...................google.com ":
      #     each_char>:each_cons(3)> 
    

    注意e 可以被认为是一个复合枚举器。我们可以通过将其转换为数组来查看此枚举器将生成​​的元素。

    e.to_a
      #=> [[" ", "D", "o"], ["D", "o", "m"], ["o", "m", "a"], ["m", "a", "i"],
      #    ["a", "i", "n"], ["i", "n", ":"], ["n", ":", "."], [":", ".", "."],
      #    [".", ".", "."], [".", ".", "."], [".", ".", "."], [".", ".", "."],
      #    [".", ".", "."], [".", ".", "."], [".", ".", "."], [".", ".", "."], 
      #    [".", ".", "."], [".", ".", "."], [".", ".", "."], [".", ".", "."],
      #    [".", ".", "."], [".", ".", "."], [".", ".", "."], [".", ".", "."],
      #    [".", ".", "."], [".", ".", "g"], [".", "g", "o"], ["g", "o", "o"],
      #    ["o", "o", "g"], ["o", "g", "l"], ["g", "l", "e"], ["l", "e", "."],
      #    ["e", ".", "c"], [".", "c", "o"], ["c", "o", "m"], ["o", "m", " "]] 
    

    继续,

    b = e.map { |before,ch,after| ch=='.' && (before=='.' || after== '.') ? ' ' : ch }
      #=> ["D", "o", "m", "a", "i", "n", ":", " ", " ", " ", " ", " ", " ", " ",
      #    " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "g", "o",
      #    "o", "g", "l", "e", ".", "c", "o", "m"] 
    b.join
      #=> "Domain:                   google.com" 
    

    使用正则表达式

    r = /
        (?<=\A|\.) # match the beginning of string or a period in a positive lookbehind
        \.         # match a period
        |          # or
        \.         # match a period
        (?=\.|\z)  # match a period or the end of the string
        /x         # free-spacing regex definition mode 
    
    str.gsub(r,' ')
      #=> "Domain:                   google.com" 
    

    【讨论】:

    • papaiatis,很高兴能为您提供帮助。
    猜你喜欢
    • 1970-01-01
    • 2021-10-05
    • 2011-01-23
    • 2012-07-22
    • 1970-01-01
    • 2011-04-21
    • 2013-11-28
    • 2018-04-19
    • 2019-06-28
    相关资源
    最近更新 更多