【问题标题】:Ruby regex capture groups in gsubgsub 中的 Ruby 正则表达式捕获组
【发布时间】:2016-05-24 20:36:33
【问题描述】:

假设我想将消息中的每个字母转换为反向字母表中的位置。为什么我似乎不能使用捕获的组并在一个 gsub 中执行它?

也许有人可以大致解释一下在 gsub 中使用捕获的组,后面的引用可以裸露(没有'')吗?我可以使用#{\1} 吗?

def decode(message)
  a = ('a'..'z').to_a
  z = a.reverse
  message.gsub!(/([[:alpha:]])/, z[a.index('\1')]) 
end

decode("the quick brown fox")

【问题讨论】:

  • \1 在此处未“初始化”。使用块,
  • 您只是想反转字符串中的单词还是专门搜索捕获组?

标签: ruby regex gsub


【解决方案1】:

请记住,方法的参数会立即计算,并将结果传递给方法。如果你想让替换适应比赛:

message.gsub!(/([[:alpha:]])/) { |m| z[a.index($1)] }

这使用了一个块,每个匹配都会被评估。

【讨论】:

  • @tadman,如您所知,这里不需要捕获组。 :-)
【解决方案2】:

使用gsub:

您的代码无法正常工作,因为 '\1' 尚未在您希望的时候被评估为其正则表达式匹配。这可以通过使用块来解决,因此定义了匹配变量:

message.gsub(/[[:alpha:]]/) { |char| z[a.index(char)] }

使用tr:

解决此类问题的一种更有效的方法是使用String#tr 来代替“用另一组字符替换一组字符”。这可以按如下方式完成:

message.tr(a.join(''), z.join(''))

【讨论】:

  • Tadman 的答案使用gsub! 而不是gsub,在这种情况下这是不好的做法并且容易出错。 (您正在改变原始对象,并且该方法可能会意外返回nil。)此外,该答案使用$1 而不是匹配结果,这也是不好的做法。 (它不是线程安全的,并且使用了不必要的变量。)
  • 是的,你的权利。我删除了我的评论。不知何故,我没有注意到您使用块变量而不是捕获组的值,说到这里,您确定要使用未使用的捕获组吗?当你看到它时,我会删除它。
  • 如果你能找到使用gsub没有块的方法,那么请分享!
  • 我说不需要(正则表达式的)捕获组。
  • 嗯,对了,我明白你的意思了。是的,当然,很公平。并不是说它有很大的不同。 :P 我已经编辑了我的答案。 (正如我所说,我什至不建议使用 gsub 来完成这项任务!)
【解决方案3】:

一种方法是操作 ASCII 值。

def code(message)
  message.gsub(/[[:alpha:]]/) { |s| (((s < 'a') ? 155 : 219 ) - s.ord).chr }
end

coded = code("the quick brown fox")
  #=> "gsv jfrxp yildm ulc" 
code(coded)
  #=> "the quick brown fox" 

注意:

'A'.ord + 'Z'.ord
  #=> 155 
'a'.ord + 'z'.ord
  #=> 219 

另一种是使用哈希:

a = ('a'..'z').to_a
Ch = a.zip(a.reverse).to_h
  #=> {"a"=>"z", "b"=>"y",..., "y"=>"b", "z"=>"a"} 

def code(message)
  message.gsub(/[[:alpha:]]/, Ch)
end

coded = code("the quick brown fox")
  #=> "gsv jfrxp yildm ulc"
code(coded)
  #=> "the quick brown fox"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-10
    • 1970-01-01
    • 1970-01-01
    • 2022-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-24
    相关资源
    最近更新 更多