bounty将在5天内到期。回答此问题可获得+200声望奖励。Ricardo Saporta正在寻找这个问题的更详细的答案:这个问题背后的意图是扩展有关RegEx的知识。为了说明好奇心,所给的例子被简化了。
这个问题是在寻找一个基于正则表达式的方法,而不是,例如,解决方案来完成示例中的任务。
有许多很棒的函数和包可以帮助解决特定的任务。
主要问题:
在\U
和\L
的脉络中,是否有一个正则表达式来保留case模式?
理想情况下,它还应该尊重单词边界和锚点。
示例
假设我们有一个很大的文本,我们想将一个单词转换为另一个单词,同时保留单词的大写。例如,将"date"
的所有示例替换为"month"
Input: `"This Date is a DATE that is daTe and date."`
Output: `"This Month is a MONTH that is moNth and month."`
input output
------ -------
"date" ~~> "month"
"Date" ~~> "Month"
"DATE" ~~> "MONTH"
"daTe" ~~> "moNth" ## This example might be asking for too much.
保留字边界
我对保留单词边界的解决方案感兴趣(即,只能匹配“整个单词”)。在给定的示例中,"date"
将更改,但"dated"
不会更改
R
现有解决方案:
我目前使用三个对sub
的嵌套调用来实现这一点。
input <- c("date", "Date", "DATE")
expected.out <- c("month", "Month", "MONTH")
sub("date", "month",
sub("Date", "Month",
sub("DATE", "MONTH", input)
)
)
目标是拥有一个pattern
和一个replace
,例如
gsub("(date)", "\\Umonth", input, perl=TRUE)
这将产生期望的输出
注意事项(2023年更新)
1.* 这个问题背后的动机是扩展有关RegEx
功能的知识。以下示例仅作为说明给出。这个问题的目的不是寻找替代的解决方法。*
1.* 该问题使用R
标签提问,但会接受调用R
中当前未提供的RegEx
风格的答案 *
4条答案
按热度按时间pbwdgjma1#
这是我认为
for
循环是合理的情况之一:@flodel
的另一个好处是实现了与通过Reduce
的循环相同的逻辑:有关这些选项的一些基准测试,请参阅@TylerRinker的答案。
nukf8bse2#
使用
gsubfn
包,您可以避免使用嵌套的子函数,并在一个调用中完成此操作。ttcibm8c3#
这里有一个qdap方法。非常简单,但不是最快的:
基准测试:
n6lpvg4x4#
你得写点逻辑
你不会找到一个纯正则表达式的解决方案。C#和javascript中类似的SO问题包含了大量的逻辑流程来确定哪些字符是大写字母。注解中链接的Perl response只有在你事先知道大写字母可以在哪个位置的情况下才有效。
此外,这些问题有额外的限制,使它们比你的问题简单得多:
1.图案和替换长度相同。
1.模式中的每个字符具有唯一的替换字符,例如
"abcd" => "wxyz"
。作为对Rust reddit上similar question的回应:
有很多种可能会出问题。例如,如果尝试替换不同数量的字符(“abc”->“wxyz”),会发生什么?如果你有一个Map有多个输出链接("aaa"->"xyz")怎么办?
这正是你试图做的。当模式和替换长度不同时,通常您希望模式中每个大写字母的索引Map到替换中的索引,例如。
"daTe" => ""moNth
。但是,有时候你不需要,例如:"DATE" => "MONTH"
,而不是"MONTh"
。regex怎么会知道呢?此外,模式或替换中的字母不保证是唯一的:您希望能够将
"WEEK"
替换为"MONTH"
,反之亦然。这排除了哈希Map方法。R方案
我写了一个函数
swap()
,它将为你做这两个字符串,即使有不同数量的字母:工作原理
swap()
函数使用Reduce()
的方式与answer非常相似:worldhorse函数是
create_replacement_pairs()
,它创建了一个实际出现在字符串中的模式对列表,例如:c("daTe", "DATE")
,并生成具有正确大小写的替换,例如c("moNth", "MONTH")
.函数逻辑为:1.查找字符串中的所有匹配项,例如
"Date" "DATE" "daTe" "date"
。1.创建一个布尔掩码,指示每个字母是否为大写。
1.如果所有字母都是大写,则替换也应该是全部大写,例如。
"DATE" => "MONTH"
.否则,如果模式中相应索引处的字母是大写,则将替换中每个索引处的字母大写。用例
这种方法不受Rust和C#答案相同的约束。我们已经看到,在替换比模式长的情况下,这是可行的。反之亦然:
此外,由于它不使用散列Map,所以它在替换中的字母不唯一的情况下工作。
最后,它也适用于模式中的字母不唯一的情况:
preserve_boundaries = FALSE
禁用它:性能
在性能方面,以这种方式从小写参数动态生成匹配将不如硬编码
list(c("Date", "Month"), c("DATE", "MONTH"), c("daTe", "moNth"), c("date", "month"))
那么快。然而,一个公平的比较应该包括键入列表所花费的时间,我怀疑即使是最忠诚的vim用户,也不可能在不到千分之一秒的时间内完成。我在Tyler Rinker的answer中看到了基准测试,所以我使用了
Reduce()
和gsub()
,这是测试中最快的替换方法。此外,这个答案中的方法生成了精确匹配和替换对,因此我们可以在gsub()
中设置fixed = TRUE
,与fixed = FALSE
相比,reduces by about 75%具有五个字符的模式进行替换的时间。