首页 文章

匹配空格但不匹配换行符

提问于
浏览
219

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

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

6 回答

  • 283

    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

  • 41

    使用双阴性:

    /[^\S\n]/
    

    避免关于 \r\n 的映射的平台差异warned about in perlport

    /[^\S\x0a\x0d]/
    

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

    使用De Morgan's law分配外部not(即字符类中的补充 ^ ),这相当于“空格而不是回车而不是换行符”,但是不要相信我的话:

    #! /usr/bin/env perl
    
    use strict;
    use warnings;
    
    use 5.005;  # for qr//
    
    my $ws_not_nl = qr/[^\S\x0a\x0d]/;
    
    for (' ', '\f', '\t', '\r', '\n') {
      my $qq = qq["$_"];
      printf "%-4s => %s\n", $qq,
        (eval $qq) =~ $ws_not_nl ? "match" : "no match";
    }
    

    输出:

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

    请注意排除垂直制表符,但这是addressed in v5.18 .

    这个技巧对于匹配字母字符也很方便 . 请记住 \w 匹配“单词字符”,字母字符以及数字和下划线 . 我们丑陋的美国人有时会想把它写成,比方说,

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

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

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

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

    if (/^[[:alpha:]]+$/) { ... }
    

    或者szbalint建议

    if (/^\p{Letter}+$/) { ... }
    
  • 10

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

    /[^\S\r\n]/
    

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

  • -4

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

    [[:blank:]]
    

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

    \p{Blank}
    

    与类似的 \h 相比,POSIX blank 由更多的正则表达式引擎(reference)支持 . 一个主要的好处是它的定义在Annex C: Compatibility Properties of Unicode Regular Expressions中是固定的,并且是支持Unicode的所有正则表达式的标准 . (例如,在Perl中, \h 选择另外包含 MONGOLIAN VOWEL SEPARATOR . )然而,支持 \h 的论据是它总是检测Unicode字符(即使引擎不同意哪些),而POSIX字符类经常默认情况下仅限ASCII(如在Java中) .

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

    • U 180E蒙古族分离器

    • U 200B ZERO WIDTH SPACE

    • U 200C ZERO WIDTH NON-JOINER

    • U 200D ZERO WIDTH JOINER

    • U 2060 WORD JOINER

    • U FEFF ZERO WIDTH NON-BREAKING SPACE

    取自https://en.wikipedia.org/wiki/White-space_character

    前面提到的蒙古元音分隔符不像修饰符那么't included for what is probably a good reason. It, along with 200C and 200D, occur within words (AFAIK), and therefore breaks the cardinal rule that all other whitespace obeys: you can tokenize with it. They' . 但是, ZERO WIDTH SPACEWORD JOINERZERO WIDTH NON-BREAKING SPACE (如果它使用的不是字节顺序标记)符合我书中的空格规则 . 因此,我将它们包含在我的水平空白字符类中 .

    在Java中:

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

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

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

    DEMO

    如果要添加回车符,请在负向前瞻中添加带有 | 运算符的 \r .

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

    DEMO

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

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

    DEMO

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

    DEMO

  • 146

    m/ /g 只需在 / / 中给出空格,它就可以了 . 或者使用 \S - 它将替换所有特殊字符,如制表符,换行符,空格等 .

相关问题