【发布时间】:2020-08-29 15:53:47
【问题描述】:
Ruby gsub 支持使用正则表达式作为模式来检测输入 并且它也可以允许使用匹配组号替换
例如,如果这是一个正则表达式检测任何单词开头的小写字母,并在其前放置一个x,在其后放置一个y
这将给出完美的结果:
"testing gsub".gsub(/(?<=\b)[a-z]/,'x\0y')
#=> "xtyesting xgysub"
但如果我想使用正则表达式将此匹配组转换为大写
在正常的正则表达式中,通常可以做到这一点\U\$0 解释为here
不幸的是,当我这样尝试时:
"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 替换中使用正则表达式,或者在 YAML 中存储诸如 &:upcase 之类的方法而不作为字符串加载,那将是完美的。
谢谢!
【问题讨论】:
-
恐怕不可能。根据文档,替换“可能包含对 \\d 形式的模式捕获组的反向引用,其中 d 是组号”。只有数字,没有字母或特殊字符。它与 Perl 的 gsub 替换逻辑不兼容。
-
(?<=\b)[a-z]应该写成\b[a-z]。而且由于不支持\U,因此无法以您想要的方式解决您的问题。 -
谢谢你们的回答,我想可能有人知道我遗漏了一些东西,再次感谢@WiktorStribiżew 我想匹配字母,也不想匹配边界,所以我想我应该使用
lookbehind来匹配字符但是,是的,我想它会给出相同的结果