匹配空格但不匹配换行符

Joe*_*Fan 258 regex perl

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

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

Gre*_*con 337

使用双阴性:

/[^\S\r\n]/
Run Code Online (Sandbox Code Playgroud)

为避免平台差异在perlport中警告有关映射^\r:

#! /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";
}
Run Code Online (Sandbox Code Playgroud)

也就是说,对于排除CR和NL的模式,不是空白或不是新行和类似.

使用De Morgan定律分配外部非(\n字符类中的补充),这相当于"空白而不是回车而不是换行",但是不要相信我的话:

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

输出:

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;
}
Run Code Online (Sandbox Code Playgroud)

请注意排除垂直制表符,但这在v5.18中得到解决.

这个技巧对于匹配字母字符也很方便.请记住,\s火柴"字样的字符,"字母,但也是数字和下划线.我们丑陋的美国人有时会想把它写成,比方说,

if (/[A-Za-z]+/) { ... }
Run Code Online (Sandbox Code Playgroud)

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

if (/[^\W\d_]+/) { ... }
Run Code Online (Sandbox Code Playgroud)

这有点不透明,因此POSIX字符类可能更好地表达意图

if (/[[:alpha:]]+/) { ... }
Run Code Online (Sandbox Code Playgroud)

或者像szbalint建议的那样

if (/\p{Letter}+/) { ... }
Run Code Online (Sandbox Code Playgroud)

  • 太可怕了. (9认同)
  • 这是非常好的.根据要求,您匹配空格(不只是**一些**空格字符),并且您排除换行符.你的解决方案并不关心这个问题:"存在什么空白字符",因为它不应该.这正是我所寻找的.(如@Rory所述,'换行'也可能包含`\ r``,例如在Windows上,所以请考虑从匹配中排除那些:`/ [^\S\r \n] /`) (8认同)
  • @Qwertie:有什么令人惊讶的?比什么更不尴尬? (6认同)
  • 聪明,但行为非常令人惊讶,我不知道它是如何不那么尴尬. (4认同)

Bor*_*din 166

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
Run Code Online (Sandbox Code Playgroud)

垂直空间图案\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
Run Code Online (Sandbox Code Playgroud)

有七个垂直空白字符匹配\v,十八个水平字符匹配\h.\s匹配二十三个字符

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

  • @AvinashRaj:这个问题是关于Perl的,它肯定支持PCRE (14认同)
  • 是什么让Perl的`\ h`稍微不标准是它包含了'蒙古语VOWEL SEPARATOR`.Unicode不认为它是空格.因此,Perl`\h`与POSIX`blank`(Perl中的`[[:blank:]]`,Java中的`\ p {Blank}`和Java 8`\h`不同.不可否认,这是一个优势. (8认同)
  • `\ h`仅适用于支持`PCRE`的语言. (6认同)
  • 想要提到的是`\ h`对于我的用例来说是完美的,它在一个或多个连续的非换行空间中在Notepad ++中进行查找/替换.没有别的(简单)有效. (6认同)
  • @AvinashRaj:除了`[[:blank:]]`不匹配不间断空格 - "&nbsp;`或`"\ xA0" (2认同)
  • @Borodin POSIX `blank` 应该与任何支持 Unicode 正则表达式的引擎中的 `NO-BREAK SPACE` 匹配。它在[附件C:Unicode正则表达式的兼容性属性](http://www.unicode.org/reports/tr18/#blank)中定义 (2认同)

Ror*_*ane 44

格雷格答案的一个变种,包括回车:

/[^\S\r\n]/
Run Code Online (Sandbox Code Playgroud)

这个正则表达式比/[^\S\n]/没有更安全\r.我的理由是Windows \r\n用于换行,并使用Mac OS 9 \r.如果\r没有\n现在的话,你不可能找到它,但是如果你找到它,除了新行之外它不会有任何意义.因此,既然\r可以表示换行符,我们也应该排除它.

  • 看起来@Greg 首先“错误”地改变了它并且没有相信你。这就是为什么我在这里投票。 (5认同)

Ale*_*sky 12

您正在寻找的是POSIX blank角色类.在Perl中,它被引用为:

[[:blank:]]
Run Code Online (Sandbox Code Playgroud)

在Java中(别忘了启用UNICODE_CHARACTER_CLASS):

\p{Blank}
Run Code Online (Sandbox Code Playgroud)

与类似的相比\h,POSIX blank由更多的正则表达式引擎(参考)支持.一个主要的好处是它的定义在附件C中得到修复:Unicode正则表达式的兼容性属性和支持Unicode的所有正则表达式的标准.(例如,在Perl中,\h选择另外包含MONGOLIAN VOWEL SEPARATOR.)但是,支持的一个参数\h是它总是检测Unicode字符(即使引擎不同意哪个),而POSIX字符类通常默认为ASCII -only(如在Java中).

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

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

在Java中:

static public final String HORIZONTAL_WHITESPACE = "[\\p{Blank}\\u200B\\u2060\\uFFEF]"
Run Code Online (Sandbox Code Playgroud)


Avi*_*Raj 11

以下正则表达式将匹配空格,但不匹配新行字符.

(?:(?!\n)\s)
Run Code Online (Sandbox Code Playgroud)

DEMO

如果你想添加回车也再加入\r|负前瞻内部操作者.

(?:(?![\n\r])\s)
Run Code Online (Sandbox Code Playgroud)

DEMO

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

(?:(?![\n\r])\s)+
Run Code Online (Sandbox Code Playgroud)

DEMO

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

DEMO


Has*_*ari 6

将下面的正则表达式放入查找部分,然后从“搜索模式”中选择正则表达式

[^\S\r\n]+
Run Code Online (Sandbox Code Playgroud)