如何替换单个字符周围的连字符

4
我希望在分词之前保留单词内部的连字符。这个策略包括用一个唯一的字符替换连字符,然后在分词后再将该唯一字符替换为连字符。注意:最终我将使用Unicode类Pd来捕获所有形式的破折号字符,但在这里我保持简单,因为我认为这部分与问题无关。
问题:当一个单词包含多个内部连字符分隔一个单字符时,它会失败。
示例和期望结果:
replaceDash <- function(x) gsub("(\\w)-(\\w)", "\\1§\\2", x)

# these are all OK
replaceDash("Hawaii-Five-O")  
## [1] "Hawaii§Five§O"
replaceDash("jack-of-all-trades")  
## [1] "jack§of§all§trades"
replaceDash("A-bomb")         
## [1] "A§bomb"
replaceDash("freakin-A")      
## [1] "freakin§A"

# not the desired outcome
replaceDash("jack-o-lantern")  # FAILS - should be "jack§o§lantern"
## [1] "jack§o-lantern"
replaceDash("Whack-a-Mole")    # FAILS - should be "Whack§a§Mole"
## [1] "Whack§a-Mole"

gsub() 的第一和第二个表达式需要哪些正则表达式模式?


1
请发布更多需要更改的输入字符串,也许可以想出一个不需要先替换任何内容就能执行的解决方案。 - Jan
1
gsub("(\\b)-(\\b)", "\\1§\\2", "jack-o-lantern") 是什么意思? - lukeA
1
gsub("(?<=\\w)-(?=\\w)", "§", "jack-o-lantern",perl=T) 是什么意思? - NicE
2
尝试使用gsub("(\\w)-(?=\\w)", "\\1§", "jack-o-lantern", perl=T)。顺便说一句,不需要使用lookbehind,因为它是一个相当昂贵的子模式。请参见IDEONE演示 - Wiktor Stribiżew
很好的解决方案,都能工作!而且解释非常有用。使用这个版本有什么理由比@lukeA更简单的建议? - Ken Benoit
2个回答

3

您可以使用带有正向先行断言的PCRE正则表达式,它将检查是否在连字符之后紧跟着一个字母字符,但不会“消耗”该字符。

replaceDash <- function(x) gsub("(\\w)-(?=\\w)", "\\1§", x, perl=T)

请参见IDEONE演示 因此,(\\w)将一个字母数字符号捕获到第1组中,后面通过\\1反向引用将其插入替换结果中,并通过(?=\\w)确保存在单词字符,但是正则表达式索引停留在连字符处,从而允许下一个匹配来自该单词字符。

-1

您没有指定允许使用哪种正则表达式功能。这里是一个使用零宽度环视的模式:

gsub("(?<=\\w)-(?=\\w)", "§", "jack-o-lantern");
# jack§o§trade

1
你没有解释就发布了别人的建议,这不公平。 - Wiktor Stribiżew
@WiktorStribiżew 请发布您的答案,它很好 :) - NicE
1
@NicE:写一篇帖子需要时间 :) - Wiktor Stribiżew
是的,确实需要时间来写一篇文章。我的帖子和其他建议同时出现了。但事实上,你的建议更好。 - PBI

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接