4

我似乎无法获得与 hashtag #、 an@或 word-boundary 匹配的正则表达式。目标是将字符串分解为类似 Twitter 的实体和主题,因此:

input = "Hello @world, #ruby anotherString" 
input.scan(entitiesRegex) 
# => ["Hello", "@world", "#ruby", "anotherString"]

要获得单词,不包括"anotherString"太大的单词,很简单:

/\b\w{3,12}\b/

将返回["Hello", "world", "ruby"]。不幸的是,这不包括主题标签和@s。它似乎应该简单地与:

/[\b@#]\w{3,12}\b/

但这会返回["@world", "#ruby"]。这让我意识到单词边界不是根据定义的字符,因此它们不属于“单个字符”的类别,因此不会匹配。更多尝试:

/\b|[@#]\w{3,12}\b/

返回["", "", "@world", "", "#ruby", "", "", ""]

/((\b|[@#])\w{3,12}\b)/

匹配正确的东西,但[[""], ["@"], ["#"], [""]]按预期返回,因为大括号也意味着捕获包含的所有内容。

/((\b|[@#])\w{3,12}\b)/

种作品。它返回[["Hello", ""], ["@world", "@"], ["#ruby", "#"]]。所以现在所有正确的项目都在那里,它们只是位于每个子数组的第一个元素处。以下代码段在技术上有效:

input.scan(/((\b|[@#])\w{3,12}\b)/).collect(&:first)

是否可以简化这一点以仅使用不需要collect后处理的正则表达式匹配并返回正确的子字符串?

4

1 回答 1

4

您可以只使用正则表达式/[@#]?\b\w+\b/。也就是说,可选地匹配一个@or #,后跟一个单词边界(在 中#ruby,该边界将在#and之间ruby,在正常单词中它也将匹配单词的开头)和一堆单词字符。

p "Hello @world, #ruby anotherString".scan(/[@#]?\b\w+\b/)
# => ["Hello", "@world", "#ruby", "anotherString"]

此外,您可以使用量词调整匹配单词应具有的字符数。您在评论中给出了一个示例,以仅#ruby通过使用来匹配已删除的答案{3,4}

p "Hello @world, #ruby anotherString".scan(/[@#]?\b\w{3,4}\b/)
# => ["#ruby"]
于 2014-03-25T13:50:05.093 回答