有时我想匹配空格,但不匹配换行符。
到目前为止,我一直在求助于[ \t]
。有没有那么尴尬的方法?
有时我想匹配空格,但不匹配换行符。
到目前为止,我一直在求助于[ \t]
。有没有那么尴尬的方法?
Answers:
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
\h
仅适用于支持的语言PCRE
。
[[:blank:]]
没有不间断的空间-
或"\xA0"
\h
对我的用例非常有效,该用例是在Notepad ++中对1个或多个连续的非换行空间进行查找/替换。没有其他(简单的)工作。
\h
稍微不符合标准的原因是它包含MONGOLIAN VOWEL SEPARATOR
。Unicode不将其视为空格。因此,Perl \h
与POSIX blank
([[:blank:]]
在Perl \p{Blank}
中为Java)和Java 8不同\h
。诚然,这是一个边缘案例。
使用双负数:
/[^\S\r\n]/
即,非空白(大写的S补充)或非回车或非换行符。用De Morgan的定律分配外部非字符(即,^
字符类中的补语),等效于“空白,但不包括回车符或换行符”。在模式中同时包含和都可以正确处理所有Unix(LF),经典Mac OS(CR)和DOS-ish(CR LF)换行符约定。\r
\n
无需相信我的话:
#! /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";
}
输出:
“” =>符合 “ \ f” =>匹配 “ \ t” =>匹配 “ \ r” =>没有匹配项 “ \ n” =>不匹配
在反对之前,Perl文档使用了相同的技术。perlrecharclass的“空白”部分的脚注如下:
在Perl v5.18之前的版本,
\s
与垂直选项卡不匹配。[^\S\cK]
(晦涩)与\s
传统做法相符。
perlrecharclass的同一部分还建议了其他方法,这些方法不会冒犯语言教师对双重否定词的反对。
超出区域设置和Unicode规则或有效的/a
开关时,“ \s
匹配,[\t\n\f\r ]
并且从Perl v5.18开始,垂直选项卡\cK
。” 放弃\r
并\n
留给/[\t\f\cK ]/
匹配的空格,但不要换行。
如果您的文本是Unicode,请使用与下面的子代码类似的代码从上述文档部分的表中构建模式。
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
匹配“单词字符”,字母字符,数字和下划线。我们丑陋的美国人有时想写成这样,
if (/[A-Za-z]+/) { ... }
但双负字符类可以遵守语言环境:
if (/[^\W\d_]+/) { ... }
用这种方式表示“单词字符,而不是数字或下划线”有点不透明。POSIX字符类更直接地传达意图
if (/[[:alpha:]]+/) { ... }
或使用szbalint建议的Unicode属性
if (/\p{Letter}+/) { ... }
\r
,例如,在Windows上,所以考虑exluding那些比赛还有:/[^\S\r\n]/
)
\h
有可用的解决方案,就没有任何借口。
Greg答案的一种变体,也包括回车符:
/[^\S\r\n]/
这个正则表达式比/[^\S\n]/
没有正则表达式更安全\r
。我的理由是Windows \r\n
用于换行,而Mac OS 9用于\r
。如果\r
没有\n
今天,您将很难找到它,但是如果您找到它,那么它除了换行符之外什么也没有。因此,由于\r
可以表示换行符,因此我们也应该排除它。
下面的正则表达式将匹配空格,但不能匹配换行符。
(?:(?!\n)\s)
如果你想添加回车也再加入\r
与|
负前瞻内部操作者。
(?:(?![\n\r])\s)
+
在非捕获组之后添加以匹配一个或多个空格。
(?:(?![\n\r])\s)+
我不知道您为什么没有提到[[:blank:]]
与任何水平空白(空格和制表符)匹配的POSIX字符类。该POSIX chracter类适用于BRE(基本正则表达式),ERE(扩展正则表达式),PCRE(与Perl兼容的正则表达式))。
您正在寻找的是POSIX blank
字符类。在Perl中,它称为:
[[:blank:]]
在Java中(不要忘记启用UNICODE_CHARACTER_CLASS
):
\p{Blank}
与同类产品相比\h
,POSIX blank
受更多的正则表达式引擎(参考)的支持。一个主要的好处是它的定义在附件C:Unicode正则表达式的兼容性属性和所有支持Unicode的正则表达式版本中的标准中得到了固定。(例如,在Perl中,\h
选择选择另外包含MONGOLIAN VOWEL SEPARATOR
。。)但是,一个值得支持的论点\h
是,它总是检测Unicode字符(即使引擎不同意也是如此),而POSIX字符类通常默认为ASCII -only(如Java)。
但是问题在于,即使坚持使用Unicode也无法100%解决问题。考虑以下在Unicode中不视为空格的字符:
U + 180E蒙古腔分隔器
U + 200B零宽度空间
U + 200C零宽度非JOINER
U + 200D零宽度接头
U + 2060 WORD JOINER
U + FEFF零宽度不间断空间
前面提到的蒙古语元音分隔符不包括在内,这可能是一个很好的原因。它与200C和200D一起出现在单词内(AFAIK),因此破坏了所有其他空格都遵循的基本规则:您可以用它进行标记。它们更像修饰符。然而ZERO WIDTH SPACE
,WORD JOINER
和ZERO WIDTH NON-BREAKING SPACE
(如果使用比字节顺序标记等)适合在我的书的空白规则。因此,我将它们包括在水平空白字符类中。
在Java中:
static public final String HORIZONTAL_WHITESPACE = "[\\p{Blank}\\u200B\\u2060\\uFFEF]"
perl
原始问题中的标签。
[\p{Blank}\u200b\u180e]
需要类似的恐怖。诚然,将元音分隔符不视为空格字符是有道理的,但是为什么零宽度空格不在诸如\s
和等类中\p{Blank}
,这使我不胜其烦。
[\r\f]
。