简体   繁体   English

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

[英]Using Ruby gsub with regex as replacement

Ruby gsub supports using regex as pattern to detect input and it also may allow to use match group number in replacement Ruby gsub支持使用正则表达式作为模式来检测输入,它也可能允许使用匹配组号来替换

for example, if that's a regex detecting lowercase letters at the beginning of any word, and puts a x before it and a y after it this would give perfect result:例如,如果这是一个检测任何单词开头的小写字母的正则表达式,并在它之前放置一个x在它之后放置一个y这将给出完美的结果:

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

But if I want to use regex to convert this match group to uppercase in normal regex, one can normally do this \\U\\$0 as explained here但是,如果我想使用正则表达式将此匹配组转换为普通正则表达式中的大写,通常可以按照此处的说明执行此\\U\\$0

unfortunately when I try like this:不幸的是,当我这样尝试时:

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

also, if I try using raw regex in replacement field like this:另外,如果我尝试在替换字段中使用原始正则表达式,如下所示:

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

I get type error:我收到类型错误:

TypeError (no implicit conversion of Regexp into String)

I'm totally aware of the option to do it using maps like this:我完全知道使用这样的地图来做这件事的选项:

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

But unfortunately, the rules (pattern, replacement) are being loaded from a .yaml file and they are applied to string this way:但不幸的是,规则(模式、替换)是从 .yaml 文件加载的,它们以这种方式应用于字符串:

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

and I am not able to store &:upcase in .yaml to be taken as a raw string我无法将&:upcase存储在 .yaml 中以作为原始字符串

A workaround I may do is to detect if upcase is the replacement got "upcase" and do it this way我可能会做的一个解决方法是检测 upcase 是否是“upcase”的替代品,然后这样做

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

But I don't want to modify this logic:但我不想修改这个逻辑:

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

If there is a workaround to either use regex in gsub replacement, or to store methods like &:upcase in YAML without being loaded as a string, it'd be perfect.如果有一种解决方法可以在gsub替换中使用正则表达式,或者在 YAML 中存储&:upcase类的方法而不作为字符串加载,那将是完美的。

Thanks!谢谢!

TL;DR TL; 博士

You can't do what you want the way you want.你不能做你想做,你想要的方式 This is documented in the Onigmo source.这在 Onigmo 源中有记录。 You'll have to use a different approach, or refactor other areas of your code to simulate the behavior you want.您必须使用不同的方法,或重构代码的其他区域来模拟您想要的行为。

Escapes Like \\U Not Available in Ruby\\U转义在 Ruby 中不可用

Special escapes like \\U are extensions to GNU sed or ported from the PCRE library.\\U这样的特殊转义符是对 GNU sed 的扩展或从 PCRE 库移植。 They are not part of Ruby's current regular expression engine.它们不是 Ruby 当前正则表达式引擎的一部分。 The Onigmo source clearly mentions that these escapes are missing: 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)

Other Approaches其他方法

You can do what you want in a number of different ways, such as using the block form of String#gsub to call String#upcase on each match.您可以通过多种不同的方式执行您想要的操作,例如使用String#gsub的块形式在每次匹配时调用String#upcase For example:例如:

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

You will also have to use the block form if you want to reliably reference certain match variables like $& or $1 , as the variables might otherwise refer to text from previous matches.如果您想可靠地引用某些匹配变量(如$&$1 ,您还必须使用块形式,否则这些变量可能会引用先前匹配中的文本。 For illustration, consider:为了说明,请考虑:

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

As this is primarily an X/Y problem, you may be happier with the answers you receive if you post a related question with an example of your YAML source and your current code for parsing your regular expression matches/substitutions.由于这主要是一个 X/Y 问题,如果您发布一个相关问题,其中包含 YAML 源示例和用于解析正则表达式匹配/替换的当前代码,您可能会对收到的答案感到满意。 Perhaps there's a way to wrap or refactor your code that you haven't considered, but you aren't going to be able to solve this the way you want.也许有一种您没有考虑过的包装或重构代码的方法,但是您将无法按照您想要的方式解决这个问题。

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

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