匹配空格但不匹配换行符

时间:2010-08-12 15:00:15

标签: regex perl

我有时想要匹配空格而不是换行符。

到目前为止,我一直在诉诸[ \t]。是否有一种不那么尴尬的方式?

6 个答案:

答案 0 :(得分:310)

使用双阴性:

/[^\S\r\n]/

即,不是空白(大写S补充)或不是回车或不换行。使用De Morgan's law分配外部not( ie ,字符类中的补充^),这相当于“空格但不是回车符或换行符。”包括两个{模式中的{1}}和\r正确处理所有Unix(LF),经典Mac OS(CR)和DOS-ish(CR LF)newline conventions

不需要接受我的话:

\n

输出:

" "  => match
"\f" => match
"\t" => match
"\r" => no match
"\n" => no match

请注意排除垂直标签,但这是addressed in v5.18

在过于严厉地反对之前,Perl文档使用相同的技术。 “Whitespace” section of perlrecharclass中的脚注为

  

在Perl v5.18之前,#! /usr/bin/env perl use strict; use warnings; use 5.005; # for qr// my $ws_not_crlf = qr/[^\S\r\n]/; for (' ', '\f', '\t', '\r', '\n') { my $qq = qq["$_"]; printf "%-4s => %s\n", $qq, (eval $qq) =~ $ws_not_crlf ? "match" : "no match"; } 与垂直标签不匹配。 \s(模糊地)匹配传统上[^\S\cK]传递的内容。

same section of perlrecharclass还提出了其他不会冒犯语言教师反对双重否定的方法。

境外语言环境和Unicode规则或\s开关生效时,“/a\s匹配,从Perl v5.18开始,垂直制表符{{1} }。“放弃[\t\n\f\r ]\cK离开\r以匹配空格而不是换行符。

如果您的文字是Unicode,请使用类似于以下子代码的代码从the aforementioned documentation section中的表格构建模式。

\n

其他应用

双重否定技巧对于匹配字母字符也很方便。请记住/[\t\f\cK ]/匹配“单词字符”,字母字符数字和下划线。我们丑陋的美国人有时会想把它写成,比方说,

sub ws_not_nl {
  local($_) = <<'EOTable';
0x0009        CHARACTER TABULATION   h s
0x000a              LINE FEED (LF)    vs
0x000b             LINE TABULATION    vs  [1]
0x000c              FORM FEED (FF)    vs
0x000d        CARRIAGE RETURN (CR)    vs
0x0020                       SPACE   h s
0x0085             NEXT LINE (NEL)    vs  [2]
0x00a0              NO-BREAK SPACE   h s  [2]
0x1680            OGHAM SPACE MARK   h s
0x2000                     EN QUAD   h s
0x2001                     EM QUAD   h s
0x2002                    EN SPACE   h s
0x2003                    EM SPACE   h s
0x2004          THREE-PER-EM SPACE   h s
0x2005           FOUR-PER-EM SPACE   h s
0x2006            SIX-PER-EM SPACE   h s
0x2007                FIGURE SPACE   h s
0x2008           PUNCTUATION SPACE   h s
0x2009                  THIN SPACE   h s
0x200a                  HAIR SPACE   h s
0x2028              LINE SEPARATOR    vs
0x2029         PARAGRAPH SEPARATOR    vs
0x202f       NARROW NO-BREAK SPACE   h s
0x205f   MEDIUM MATHEMATICAL SPACE   h s
0x3000           IDEOGRAPHIC SPACE   h s
EOTable

  my $class;
  while (/^0x([0-9a-f]{4})\s+([A-Z\s]+)/mg) {
    my($hex,$name) = ($1,$2);
    next if $name =~ /\b(?:CR|NL|NEL|SEPARATOR)\b/;
    $class .= "\\N{U+$hex}";
  }

  qr/[$class]/u;
}

但是双负字符类可以尊重语言环境:

\w

表达“单词字符但不是数字或下划线”这种方式有点不透明。 POSIX字符类更直接地传达意图

if (/[A-Za-z]+/) { ... }

或建议使用szbalint的Unicode属性

if (/[^\W\d_]+/) { ... }

答案 1 :(得分:158)

Perl版本5.10及更高版本支持辅助垂直和水平字符类\v\h,以及通用空白字符类\s

最干净的解决方案是使用水平空白字符类\h。这将匹配ASCII集中的制表符和空格,扩展ASCII中的不间断空格或任何这些Unicode字符

U+0009 CHARACTER TABULATION
U+0020 SPACE
U+00A0 NO-BREAK SPACE (not matched by \s)

U+1680 OGHAM SPACE MARK
U+2000 EN QUAD
U+2001 EM QUAD
U+2002 EN SPACE
U+2003 EM SPACE
U+2004 THREE-PER-EM SPACE
U+2005 FOUR-PER-EM SPACE
U+2006 SIX-PER-EM SPACE
U+2007 FIGURE SPACE
U+2008 PUNCTUATION SPACE
U+2009 THIN SPACE
U+200A HAIR SPACE
U+202F NARROW NO-BREAK SPACE
U+205F MEDIUM MATHEMATICAL SPACE
U+3000 IDEOGRAPHIC SPACE

垂直空间模式\v不太有用,但匹配这些字符

U+000A LINE FEED
U+000B LINE TABULATION
U+000C FORM FEED
U+000D CARRIAGE RETURN
U+0085 NEXT LINE (not matched by \s)

U+2028 LINE SEPARATOR
U+2029 PARAGRAPH SEPARATOR

有七个与\v匹配的垂直空白字符和与\h匹配的十八个水平字符。 \s匹配二十三个字符

所有空格字符都是垂直水平且没有重叠,但它们不是正确的子集,因为\h也匹配U + 00A0 NO-BREAK SPACE ,\v也匹配U + 0085 NEXT LINE,两者都不匹配\s

答案 2 :(得分:43)

Greg’s answer的变体,包括回车:

/[^\S\r\n]/

此正则表达式比/[^\S\n]/更安全,没有\r。我的理由是Windows使用\r\n表示换行符,Mac OS 9使用\r。如今,如果没有\r,你就不可能找到\n,但如果找到它,除了新行之外,它不会有任何意义。因此,由于\r可能意味着换行符,因此我们也应将其排除在外。

答案 3 :(得分:11)

您正在寻找的是POSIX blank字符类。在Perl中,它被引用为:

[[:blank:]]
Java中的

(不要忘记启用UNICODE_CHARACTER_CLASS):

\p{Blank}

与类似的\h相比,更多的正则表达式引擎(reference)支持POSIX blank。一个主要的好处是它的定义在Annex C: Compatibility Properties of Unicode Regular Expressions中得到修复,并且是支持Unicode的所有正则表达式的标准。 (例如,在Perl中,\h选择另外包含MONGOLIAN VOWEL SEPARATOR。但是,支持\h的论据是它始终检测Unicode字符(即使引擎不是' t同意哪个),而POSIX字符类通常默认只使用ASCII(如在Java中)。

但问题是,即使坚持使用Unicode也无法100%解决问题。请考虑以下在Unicode中不被视为空格的字符:

上述蒙古元音分隔符不包括在内可能是一个很好的理由。它与200C和200D一起出现在单词(AFAIK)中,因此打破了所有其他空白服从的基本规则:你可以用它进行标记。它们更像是修饰语。但是,ZERO WIDTH SPACEWORD JOINERZERO WIDTH NON-BREAKING SPACE(如果它使用的不是字节顺序标记)符合我的书中的空格规则。因此,我将它们包含在我的水平空白字符类中。

在Java中:

static public final String HORIZONTAL_WHITESPACE = "[\\p{Blank}\\u200B\\u2060\\uFFEF]"

答案 4 :(得分:10)

以下正则表达式将匹配空格,但不匹配换行符。

(?:(?!\n)\s)

DEMO

如果您还要添加回车符,请在负向预告中添加\r |运算符。

(?:(?![\n\r])\s)

DEMO

在非捕获组之后添加+以匹配一个或多个空格。

(?:(?![\n\r])\s)+

DEMO

我不知道为什么你们没有提到匹配任何水平空格(空格和制表符)的POSIX字符类[[:blank:]]。此POSIX chracter类可用于BRE( Basic REgular Expressions ),ERE(扩展正则表达式),PCRE( Perl兼容正则表达式)。

DEMO

答案 5 :(得分:-3)

m/ /g只需在/ /中添加空格即可。或者使用\S - 它将替换所有特殊字符,如制表符,换行符,空格等。