【问题标题】:Regex: how to match an word that doesn't end with a specific character正则表达式:如何匹配不以特定字符结尾的单词
【发布时间】:2012-01-01 03:44:21
【问题描述】:

我想匹配整个“单词”——一个以数字字符开头并且可能包含特殊字符但不以 '%' 结尾的单词。

匹配这些:

  • 112(整数)
  • 10-12(范围)
  • 11/2(分数)
  • 11.2(十进制数)
  • 1,200(千位分隔符)

但不是

  • 12%(百分比)
  • A38(以字母字符开头的单词)

我试过这些正则表达式:

(\b\p{N}\S)*)

但在“12%”中返回“12%”

(\b\p{N}(?:(?!%)\S)*)

但在“12%”中返回“12”

我可以对忽略%\S 术语进行例外处理吗? 还是必须做其他事情?

我将在 PHP 中使用它,但您可以随意编写,我会将其转换为 PHP。

【问题讨论】:

  • 这些数字是否出现在某些上下文中?周围的空间等?具体来说,您为什么使用尾随 \S(表示非空格)?

标签: php regex numbers word match


【解决方案1】:

这符合您的规范:

\b\p{N}\S*+(?<!%)

说明:

\b       # Start of number
\p{N}    # One Digit
\S*+     # Any number of non-space characters, match possessively
(?<!%)   # Last character must not be a %

possessive quantifier\S*+ 确保正则表达式引擎不会回溯到它已经匹配的非空格字符字符串。因此,它不会“回馈”% 以匹配 12% 内的 12

当然,这也将匹配 1!abc,因此您可能希望比匹配任何非空白字符的 \S 更具体。

【讨论】:

  • +1,但如果你将 \S* 设为所有格 - \S*+ - 你可以去掉 (?=\s|$)
  • @AlanMoore:很好的建议。我会这样做的。
  • 谢谢。这完美地工作。我对它进行了一些扩展,以适应我发现的其他一些情况。 (\b\p{N}\S*+(?&lt;!%|%\p{P}|%\p{P}\p{P})) 所以它忽略了“12%”、“11%-12%”、“(12%)”和“(12%)”。在我的数据中,% 后面最多有两个标点符号,但我确信如果需要,上面的代码可以转换为更通用的代码。
【解决方案2】:

我可以对忽略 % 的 \S 术语做一个例外

是的,你可以:

[^%\s]

看到这个表达式\b\d[^%\s]*here on Regexr

【讨论】:

  • 但他说只有最后一个字符不能是%
  • @TimPietzcker 没错,然后我只展示了从预定义类中排除特定字符的方法,因为正确答案已经从你那里得到 (+1)
  • 是的,他也要求这样做(排除单个字符)。所以我们真的不知道他真正需要什么:) +1!
  • 谢谢。我肯定会更多地使用它。
【解决方案3】:
\d+([-/\.,]\d+)?(?!%)

解释:

\d+        one or more digits
(
   [-/\.,]     one "-", "/", "." or ","
   \d+         one or more digits
)?         the group above zero or one times
(?!%)      not followed by a "%" (negative lookahead)

【讨论】:

  • +1。从提供的示例来看,我怀疑这是 OP 应该 提出的问题的答案。 ;)
  • @AlanMoore:小心,这将匹配12% 中的1。量词也应该是所有格。然后它会工作。
  • @Tim:我可以通过说我假设正则表达式周围存在单词边界或锚点来从这种失态中恢复过来吗? :P
【解决方案4】:

KISS(限制性):

/[0-9][0-9.,-/]*\s/

【讨论】:

  • 这将匹配12 in 12%
  • 我假设 OP 正在寻找“数字”,所以“7ISNOTANUMBER”不应该匹配,因此应该有某种分隔符(我认为是空格)。
【解决方案5】:

试试这个

preg_match("/^[0-9].*[^%]$/", $string);

【讨论】:

  • 不能匹配个位数。
【解决方案6】:

试试这个 PCRE 正则表达式:

/^(\d[^%]+)$/

它应该能满足你的需要。

【讨论】:

  • 只有最后一个字符不能是百分号。
【解决方案7】:

我只建议:

(\b[\p{N},.-]++(?!%))

关于十进制分隔符或范围,这不是很准确。 (例如)。但是++所有格量词会吃掉尽可能多的小数。所以你真的只需要用一个简单的断言来检查下面的字符。对你的例子有用。

【讨论】:

  • OP 确实说第一个字符必须是一个数字,而您并没有强制执行。领先的\b 不能解决问题;它将匹配(例如)foo,bar 中的逗号。
  • 就像我说的,不是很准确。 etuardu 已经回答了正确的范围和分数处理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-02
  • 2013-08-26
  • 1970-01-01
  • 2016-06-21
  • 2017-09-12
相关资源
最近更新 更多