替换非单词字符,除非给定序列匹配

时间:2015-08-21 01:17:09

标签: ruby regex string

我有一个这样的字符串:

"Jim-Bob's email @@@hl@@@address@@@endhl@@@ is: jb@example.com"

除了@@@分隔符之外,我想替换所有非单词字符(符号和空格)。

我目前正在使用:

str.gsub(/[^\w@]+/, 'X')

产生:

"JimXBobXsXemailX@@@hl@@@address@@@endhl@@@XisXjb@exampleXcom"

在实践中,这已经足够了,但它有两个原因让我感到不快:

  • 电子邮件地址中的@未被替换。
  • 使用[^\w]代替\W感觉很草率。

如何替换所有非单词字符,除非这些字符组成@@@hl@@@@@@endhl@@@分隔符字符串?

2 个答案:

答案 0 :(得分:2)

str.gsub(/(@@@.*?@@@|\w+)|./) { $1 || "X" }
# => "JimXBobXsXemailX@@@hl@@@address@@@endhl@@@XisXXjbXexampleXcom"

这种方法使用交替工作类似于case结构的事实:第一个匹配的消耗相应的字符串,然后不再对其进行匹配。因此,@@@.*?@@@将消耗一个标记(如@@@hl@@@;其中没有其他内容匹配。我们还匹配任何单词字符序列。如果捕获了其中任何一个,我们可以将它们返回为 - 是($1)。如果没有,那么我们匹配任何其他字符(即不在标记内,而不是单词字符),并将其替换为"X"

答案 1 :(得分:1)

关于你的第二点,我认为你问的太多了;没有简单的方法可以避免这种情况。

关于第一点,一个简单的方法是暂时用您永远不会使用的字符替换"@@@"(假设您使用的系统没有"\r",因此不使用该字符;我们可以将其用作时间替代品。)

"Jim-Bob's email @@@hl@@@address@@@endhl@@@ is: jb@example.com"
.gsub("@@@", "\r").gsub(/[^\w\r]/, "X").gsub("\r", "@@@")
# => "JimXBobXsXemailX@@@hl@@@address@@@endhl@@@XisXXjbXexampleXcom"