我可以对 POSIX 括号表达式进行否定吗?

Can I do a negation of a POSIX bracket expression?

我知道我可以搜索匹配 space 和 POSIX 括号表达式 [[:space:]] 的内容。我可以使用 POSIX 括号表达式搜索与 space 不匹配的内容吗?特别是,它应该匹配的字符包括字母和括号 (().

[[:graph:]] 看起来有点模糊:

[[:graph:]] - Non-blank character (excludes spaces, control characters, and similar)

嗯,如果

'foo bar'[ /[[:space:]]/ ] # => " "

匹配 space,为什么这行不通?

'foo bar'[ /[^[[:space:]]]/ ] # => "f"

例如,像这样:

'foo bar'.scan(/[^[[:space:]]]+/) # => ["foo", "bar"]

重要的是要记住 [[:space:]] 是一个字符 class,就像 \s\d 或它们的否定版本一样。由于 \S 类似于 [^\s] 我们可以使用 [^[[:space:]]].


I think that should be [^[:space:]] since [:space:] is what expands inside the set notation [...].

我使用 [[...]] 形式,因为那是 Regexp 中记录的内容。

为清楚起见,这里有一些示例没有使用文档中所示的双括号,而是遵循以下注释:

'foo bar'[ /[[:space:]]/    ]# => " "
'foo bar'[ /[^[:space:]]/   ]# => "f"
'foo bar'[ /[^[[:space:]]]/ ]# => "f"

请注意,这不起作用:

'foo bar'[ /[:space:]/      ]# => "a"

/[:space:]/ 被正则表达式引擎解释为:

/[:space]/ 

这是一个常规字符集,不是元形式。这就是它在 "foo bar".

中匹配 'a' 的原因

你在这里混淆了两件事:bracket expression and a POSIX character class。外层的 [...] 是括号表达式,可以用 [ 后面的 ^ 取反。 POSIX 字符 class 是一个 [:+name+:] 结构,只能在方括号表达式中使用。

因此,在您的情况下,[[:space:]] 模式是一个括号表达式,仅包含 1 个 POSIX 字符 class 匹配空格:

  • [ - 左括号表达式
    • [:space:] - POSIX 字符 class 用于空格
  • ] - 括号表达式的右括号。

要否定它,只需像通常的 NFA character classes 一样添加 ^[^[:space:]].

请注意,我故意区分术语 "bracket expression"、"POSIX character class" 和 "character class",因为 POSIX 和常见的 NFA 正则表达式世界遵循不同的术语。

看来这个变体也能解决问题:

/[[:^alpha:]]+/.match("ab12")

结果:

#<MatchData "12">