如何匹配除特定字符外的任何非空格字符?

162
在Perl中,\S匹配任何非空格字符。
如何匹配除反斜杠\以外的任何非空白字符?
6个回答

201

您可以使用一个字符类

/[^\s\\]/

匹配任何非空格字符或\。以下是另一个示例:

[abc]表示“匹配abc”; [^abc]表示“匹配除abc之外的任何字符”。


^ 被解释为否定时,何时被解释为行开头?在这方面,为什么 $0~/\s*^\s/ 不能匹配以一定数量的空格开头的行? - Alexander Cska
1
在字符类之外,它表示“字符串的开头”(或行,取决于当前匹配模式)。在字符类内,仅当它是开括号后的第一个字符时,它才否定字符类的内容。 - Tim Pietzcker
以下代码是否匹配以一些空格开头的行 $0~/\s*^\s/,后面跟着任何非空格字符? - Alexander Cska
1
那可能是 /^\s+/ - 行首加上一个或多个空白字符。 - Tim Pietzcker
很遗憾,它不起作用。我正在尝试匹配一行,如果它以缩进开头。 - Alexander Cska
1
@AlexanderCska,你搞定了吗?上面的答案只会返回字符串的第一个匹配项。如果您想要返回所有匹配项,请添加“g”修饰符。/[^\s\\]/g - Ben Carp

17

你可以使用向前查看:

/(?=\S)[^\\]/

2
它会向前查看,如果不是空格。然后负类接受除你的类中的字符以外的任何东西(即不是空格)。 - Denis de Bernardy
我喜欢这个解决方案。它非常适合像“给我除空格以外的所有非单词字符”这样的需求:/(?=\S)\W/ - jocull
我曾遇到这样的情况,需要匹配任何非空格字符以及非引号字符。同时,它还需要允许包含空格,例如:THIS IS A TEST, AND AGAIN。下面的正则表达式对我非常有效:(?=\S)[^"]* - Arvo Bowen
接受的答案对我没用,但这个有用。我在Sublime Text的正则表达式搜索中使用了它。 - Christian Noel
我正在寻找如何选择除 - 以外的任何非单词字符,这里是 /(?=\W)[^-]/g - Taufik Nurhidayat

13

对我而言,使用 sed 能解决这个问题 [编辑: 下面的评论指出 sed 不支持 \s]

[^ ]

当......的时候

[^\s] 

没做过

# Delete everything except space and 'g'
echo "ghai ghai" | sed "s/[^\sg]//g"
gg

echo "ghai ghai" | sed "s/[^ g]//g"
g g

3
\s 不仅匹配空格字符,还包括制表符、换行符、回车符等(具体有多少取决于正则表达式的语法)。这是 Perl 发明的,最初是 POSIX 字符类 [:space:] 的速记方式,并且不受 sed 支持。您上面的第一个正则表达式应该是 s/[^[:space:]g]//g - Alan Moore
Yup @AlanMoore 的代码可以正常工作:echo "ghai ghai" | sed "s/[^[:space:]g]//g",输出结果为:g g - storm_m2138

2

在我的系统上:CentOS 5

我可以在集合之外使用\s,但必须在集合内使用[:space:]。实际上,我只能在集合内使用[:space:]。因此,要使用此功能匹配单个空格,我必须使用[[:space:]],这真的很奇怪。

echo a b cX | sed -r "s/(a\sb[[:space:]]c[^[:space:]])/Result: \1/"

Result: a b cX
  • 我会用\s来匹配第一个空格
  • 我会用[[:space:]]来交替匹配第二个空格
  • 我会用[^[:space:]]来匹配除空格以外的任何字符X

以下两种方法不起作用:

a[:space:]b  instead use a\sb or a[[:space:]]b

a[^\s]b      instead use a[^[:space:]]b

1
截至sed 4.4版本,显然仍需使用([^[:space:]])而非([^\s])。我正在使用openSUSE Tumbleweed 2018 04 03。 - user2394284

0
在这种情况下,更容易将“非反斜杠的非空格字符”问题定义为不是“空格或反斜杠”,正如接受的答案所示
/[^\s\\]/

然而,对于更棘手的问题,正则表达式集合功能可能会很方便。您可以在字符类上执行集合操作以获得所需内容。这个示例从非空白字符集中减去仅为反斜杠的集合:

use v5.18;
use experimental qw(regex_sets);

my $regex = qr/abc(?[ [\S] - [\\] ])/;


while( <DATA> ) {
    chomp;
    say "[$_] ", /$regex/ ? 'Matched' : 'Missed';
    }

__DATA__
abcd
abc d
abc\d
abcxyz
abc\\xyz

输出结果显示,在 c 之后既没有空格也没有反斜杠匹配:
[abcd] Matched
[abc d] Missed
[abc\d] Missed
[abcxyz] Matched
[abc\\xyz] Missed

当更大的集合难以优雅地表达时,使用集合操作可以使其更加精细。在这个例子中,我更愿意看到集合操作:

[b-df-hj-np-tv-z]
(?[ [a-z] - [aeiou] ])

0
如果在bash或grep中使用正则表达式而不是仅在perl中使用,\S无法匹配所有非空格字符。然而,\S的等效项是[^\r\n\t\f\v ]。
因此,与其使用this
[^\s\\]

......你需要这样做,以匹配无空格字符(正则表达式:\r\n\t\f\v无反斜杠(\; 正则表达式:\\

[^\r\n\t\f\v \\]

参考资料:

  1. [我的回答] Unix & Linux:任何非空白正则表达式

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接