我正在尝试使用ruby on rails为一个简单的大学项目提取主题标签。我面临的问题是只包含数字的标签和没有空格的标签。
text = "Pack my #box with #5 dozen liquor.#jugs link.com/liquor#jugs #2good #first#second"
我的正则表达式是/(?:^|\s)#(\w+)/i
(source)
此正则表达式返回#["box", "5", "2good", "first"]
如何确保它只返回#["box", "2good"]
并忽略其余部分,因为它们不是'真正的'标签?
答案 0 :(得分:10)
你能试试这个正则表达式吗?
/(?:^|\s)(?:(?:#\d+?)|(#\w+?))\s/i
更新1:
在某些情况下,上述正则表达式不匹配:#blah23blah和#23blah23。
因此修改了正则表达式以处理所有情况。
正则表达式:
/(?:\s|^)(?:#(?!\d+(?:\s|$)))(\w+)(?=\s|$)/i
细分:
(?:\s|^)
- 匹配前面的空格或行首。才不是
抓住比赛。#
- 匹配哈希但不捕获。(?!\d+(?:\s|$)))
- 负面避免所有数字字符的前瞻性
在#和空间之间(或行尾)(\w+)
- 匹配并捕获所有单词字符(?=\s|$)
- 正面前瞻以确保跟随空格或结尾
线。这是确保它匹配相邻的有效哈希标记所必需的。修改了示例文本以捕获大多数情况:
#b> #blah用#5打#ack2#3good酒包装我的#box。#jugs link.com/liquor#jugs#mkvef214asdwq sd#3e4 flsd#2good#first#second#3
匹配
比赛1:等等
比赛2:方框
比赛3:good2
比赛4:3好
第5场比赛:mkvef214asdwq
比赛6:3e4
比赛7:2好的
更新2:
要排除以下划线开头或结尾的单词,只需将您的排除项包含在否定前瞻中,如下所示:
/(?:\s|^)(?:#(?!(?:\d+|\w+?_|_\w+?)(?:\s|$)))(\w+)(?=\s|$)/i
示例,正则表达式和匹配项记录在此Rubular link
中答案 1 :(得分:2)
我会这样做:
text.scan(/ #[[:digit:]]?[[:alpha:]]+ /).map{ |s| s.strip[1..-1] }
返回:
[
[0] "box",
[1] "2good"
]
我不会尝试在正则表达式中做所有事情。我更喜欢让它们尽可能简单,然后在我获得基本数据后过滤和毁坏。我的理由是正则表达式更难以维持它们变得越复杂。我宁愿把时间花在维护模式上的其他事情上。
答案 2 :(得分:1)
试试这个:
/\s#([[\d]]?[[a-z]]+\s)/i
输出:
1.9.3-p194 :010 > text = "Pack my #box with #5 dozen liquor.#jugs link.com/liquor#jugs #2good #first#second"
=> "Pack my #box with #5 dozen liquor.#jugs link.com/liquor#jugs #2good #first#second"
1.9.3-p194 :011 > puts text.scan /\s#([[\d]]?[[a-z]]+\s)/i
box
2good
=> nil