繁体   English   中英

使用带有正则表达式的 Ruby gsub 作为替换

[英]Using Ruby gsub with regex as replacement

Ruby gsub支持使用正则表达式作为模式来检测输入,它也可能允许使用匹配组号来替换

例如,如果这是一个检测任何单词开头的小写字母的正则表达式,并在它之前放置一个x在它之后放置一个y这将给出完美的结果:

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

但是,如果我想使用正则表达式将此匹配组转换为普通正则表达式中的大写,通常可以按照此处的说明执行此\\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 中以作为原始字符串

我可能会做的一个解决方法是检测 upcase 是否是“upcase”的替代品,然后这样做

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

但我不想修改这个逻辑:

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

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

谢谢!

TL; 博士

你不能做你想做,你想要的方式 这在 Onigmo 源中有记录。 您必须使用不同的方法,或重构代码的其他区域来模拟您想要的行为。

\\U转义在 Ruby 中不可用

\\U这样的特殊转义符是对 GNU sed 的扩展或从 PCRE 库移植。 它们不是 Ruby 当前正则表达式引擎的一部分。 Onigmo 消息来源清楚地提到缺少这些转义:

 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 源示例和用于解析正则表达式匹配/替换的当前代码,您可能会对收到的答案感到满意。 也许有一种您没有考虑过的包装或重构代码的方法,但是您将无法按照您想要的方式解决这个问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM