使用Ruby gsub和正则表达式作为替换

问题描述

Ruby gsub支持使用正则表达式作为模式来检测输入 并且还可能允许在替换中使用匹配组号

例如,如果这是一个正则表达式,则在任何单词的开头都检测到小写字母,并在其前面放置x,在其后面放置y 这样会产生完美的结果:

"testing gsub".gsub(/(?<=\b)[a-z]/,'x\0y')
#=> "xtyesting xgysub"

但是如果我想使用正则表达式将此匹配组转换为大写 在正常的正则表达式中,通常可以按照here

的说明进行此操作\U\$0

不幸的是,当我这样尝试时:

"testing gsub".gsub(/(?<=\b)[a-z]/,'\U\0')
#=> "\\Utesting \\Ugsub"

此外,如果我尝试在这样的替换字段中使用原始正则表达式:

"testing gsub".gsub(/(?<=\b)[a-z]/,/\U\0/)`

我输入错误:

TypeError (no implicit conversion of Regexp into String)

我完全知道可以使用如下地图进行选择:

"testing gsub".gsub(/(?<=\b)[a-z]/,&:upcase)

但是不幸的是,这些规则(样式,替换)是从.yaml文件中加载的,它们通过以下方式应用于字符串:

input.gsub(rule['pattern'],rule['replacement'])

并且我无法将&:upcase存储在.yaml中作为原始字符串

我可以采取的解决方法是检测大写替换是否为“大写” 并以此方式

"testing gsub".gsub(/(?<=\b)[a-z]/) {|l| l.send("upcase")}

但我不想修改此逻辑:

input.gsub(rule['pattern'],rule['replacement'])

如果有一种解决方法,可以在gsub替换中使用正则表达式,或者将&:upcase之类的方法存储在YAML中而不以字符串形式加载,那么这将是完美的选择。

谢谢!

解决方法

TL; DR

您无法想要做什么。这在Onigmo来源中有记录。您将必须使用其他方法,或重构代码的其他区域以模拟所需的行为。

\U这样的转义在Ruby中不可用

特殊的转义,例如\U是PCRE库中对sed或移植的GNU的扩展。它们不是Ruby当前正则表达式引擎的一部分。 Onigmo source明确提到缺少这些转义符:

A-3. Missing features compared with perl 5.18.0

   + \N{name},\N{U+xxxx},\N
   + \l,\u,\L,\U,\C
   + \v,\V,\h,\H
   + (?{code})
   + (??{code})
   + (?|...)
   + (?[])
   + (*VERB:ARG)

其他方法

您可以通过多种不同的方式来完成自己想做的事情,例如使用String#gsub的块形式在每次比赛中调用String#upcase。例如:

"testing gsub".gsub(/\b\p{Lower}+/) { |m| m.upcase }
#=> "TESTING GSUB"

如果您要可靠地引用某些匹配变量,例如$&$1,则还必须使用块形式,因为否则这些变量可能引用以前匹配中的文本。为了说明,请考虑:

"foo bar".gsub /\b\p{Lower}+/,"#{$&.upcase}"
#=> "BAR BAR"

由于这主要是一个X / Y问题,如果您发布相关问题并附上您的YAML源代码示例以及当前用于解析正则表达式匹配项/替换项的代码,则您可能会更满意收到的答案。也许有一种方法可以包装或重构您尚未考虑的代码,但是您将无法以所需的方式解决此问题。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...