post 标记系统中文本的正确正则表达式

Proper regex for text in a post tagging system

我正在创建一个基本上是 SO 克隆的练习,并且我正在尝试实现一个标记系统,尽管我在使用标记名称的正则表达式时遇到了一些问题。

我正在努力实现与 Whosebug 的标签相同的结果,即:

这些应该 return 肯定匹配:

exampletag
example-tag
ex-ample-tag
ex_ample_tag
ex-ample_tag
ex.am-ple_tag
Ex.4m-p1e_t4g

并且这些应该 return 为负数,为了这个问题假设空白意味着新标签的开始并且此时可以安全地被忽略

ex-am-pl-et-ag // and variations where there's more than 3 `-` `_` or `.`
-exampletag // no starting symbols
exampletag- // no trailing symbols

我目前在正则表达式中停留在这一点上,我不确定如何制定它better/further

((\w+)(\-|\_|\.)?)?

以及我的推理

(                    Capture the sequence of #2 and #3 into capture group #1
  (                  Capture group #2
    \w+              One or more alphanumericals
  )
  (                  Capture group #3
    \-|\_|\.         - _ or .
  )?                 0 or 1 of the preceding
)
  ?                0 or 1 of capture group #1

</code> 部分并没有像我预期的那样工作。这将匹配 <code>example- 之类的内容,但 tag 部分将是次要命中,我不知道如何从这里开始。

最好我希望此正则表达式与正则表达式的 Ruby 风格一起工作,但无论哪种风格都很好。

请注意 \w 匹配字母、数字和下划线。因此,在模式中使用 \w 时检查下划线的数量永远不会准确。此外,您的模式只匹配一系列一个或多个单词字符,后跟可选的 -_.,然后 ? 尝试有选择地匹配 与当前位置右侧立即捕获到组 1 中的值相同

我建议将所有 \w 更改为 [^\W_] 以从 \w 中排除(减去)_,一个类似于 a(?:ba){0,3} 的结构来匹配元素分隔项,并至少使用 ^$ 锚点来匹配字符串的开头和结尾。

你可以使用

^[^\W_]+(?:[-_.][^\W_]+){0,3}$

在Ruby中,必须写成

\A[^\W_]+(?:[-_.][^\W_]+){0,3}\z

详情

  • \A - 字符串开头
  • [^\W_]+ - 除了 _
  • 之外的一个或多个单词字符
  • (?:[-_.][^\W_]+){0,3} - -/_/. 出现零次、一次、两次或三次,然后是 [=15 以外的一个或多个单词字符=]
  • \z - 字符串结尾。

参见regex demo