【问题标题】:Exclude characters from a character class从字符类中排除字符
【发布时间】:2018-08-26 01:37:49
【问题描述】:

有没有一种简单的方法来匹配一个类中的所有字符,除了某些字符集?例如,如果在我可以使用 \w 匹配所有 unicode 单词字符集的语言中,有没有办法从匹配中排除下划线“_”之类的字符?

我想到的唯一想法是在每个字符周围使用负前瞻/后视,但是当我实际上只想将一个字符与正匹配和负匹配进行匹配时,这似乎比必要的复杂。例如,如果 & 是 AND 运算符,我可以这样做...

^(\w&[^_])+$

【问题讨论】:

  • 您使用的是哪种风格的正则表达式? (例如 Perl、Java 等)
  • 什么正则表达式风格/语言? stackoverflow.com/q/3201689/139010
  • 在 .NET 中,您可以使用 [\w-[_]] 排除下划线。
  • 我最常使用的正则表达式引擎是基于 java 的,虽然是一个旧的实现(无论 CF8 在后台使用什么)。但是我在 javascript 和 python 中也有这个需求。
  • 你是说ColdFusion?那是基于 JavaScript,而不是 Java。而且它的\w 只识别ASCII 字字符([A-Za-z0-9_]),而不是完整的Unicode 集。 Python 的内置 re 风格也是如此。

标签: regex set-difference character-class


【解决方案1】:

这真的取决于你的正则表达式风格。

.NET

... 仅提供一种简单的字符类集操作:subtraction。这对你的例子来说已经足够了,所以你可以简单地使用

[\w-[_]]

如果- 后跟一个嵌套字符类,则将其减去。就这么简单……

Java

... 提供了更丰富的character class set operations 集合。特别是你可以得到两个集合的交集,比如[[abc]&&[cde]](在这种情况下会给出c)。交集和否定一起给你减法:

[\w&&[^_]]

Perl

... 支持在 extended character classes 上的设置操作作为实验性功能(自 Perl 5.18 起可用)。特别是可以直接减去任意字符类:

(?[ \w - [_] ])

所有其他口味

...(支持前瞻)允许您通过使用负前瞻来模拟减法:

(?!_)\w

这首先检查下一个字符不是_,然后匹配任何\w(由于负前瞻,它不能是_)。

请注意,这些方法中的每一个都是完全通用的,因为您可以减去两个任意复杂的字符类。

【讨论】:

    【解决方案2】:

    您可以使用 \w 类的否定 (--> \W) 并将其排除:

    ^([^\W_]+)$
    

    【讨论】:

    • 创意,但我不认为OP期望这种答案,他想在一般情况下排除一个字符。好主意虽然
    • @CasimiretHippolyte 我应该想到这一点。 HamZa 是对的,我正在寻找更一般的案例,但是哇... \p... 感谢您指出这一点,因为我从未使用过它。
    • @CasimiretHippolyte 不是所有个案例。这不能用于从范围中排除字符;)。
    • 并非所有 RE 引擎都支持。
    • @DonalFellows 你说的“那个”是什么意思?否定字符类?
    【解决方案3】:

    就我理解您的问题而言,负前瞻是正确的方法:

    ^((?!_)\w)+$
    

    【讨论】:

      【解决方案4】:

      这可以在 python 中使用regex module 完成。比如:

      import regex as re
      pattern = re.compile(r'[\W_--[ ]]+')
      cleanString = pattern.sub('', rawString)
      

      您通常会使用pip 安装正则表达式模块:

      pip install regex
      

      编辑

      正则表达式模块有两种行为,版本 0 和版本 1。设置减法(如上)是版本 1 的行为。 pypi 文档声称版本 1 是默认行为,但您可能会发现情况并非如此。你可以检查

      import regex
      if regex.DEFAULT_VERSION == regex.VERSION1:
        print("version 1")
      

      将其设置为版本 1:

      regex.DEFAULT_VERSION = regex.VERSION1
      

      或在单个表达式中使用版本一:

      pattern = re.compile(r'(?V1)[\W_--[ ]]+')
      

      【讨论】:

      • VERSION1 位上的救生员。否则我会发疯的。
      【解决方案5】:

      尝试使用减法:

      [\w&&[^_]]+
      

      注意:这适用于 Java,但可能不适用于其他 Regex 引擎。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-02-14
        相关资源
        最近更新 更多