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;
}
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
vertical 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
8条答案
按热度按时间wfveoks01#
摘要
\h
匹配水平空格,自v5.10.0(2007年发布)起在perl中使用[^\S\r\n]
\p{Blank}
或\p{HorizSpace}
[\t\f\cK ]
水平空白
perlre的“字符类和其他特殊转义”部分包括
\h
水平空白\H
不是水平空白双重否定
如果你可能会在其他引擎上使用你的模式,特别是那些不是Perl-compatible或者不支持
\h
的引擎,那么用双重否定来表达它:也就是说,not-not-whitespace(大写的
S
补码)或not-carriage-return或not-newline。用De Morgan’s law分配外部not(* 即括号中的字符类中的补码^
),这相当于从\s
中减去\r
和\n
。在模式中同时包含回车符和换行符可以正确处理所有Unix(LF)、经典Mac OS(CR)和DOS风格(CRLF)的换行符约定。不用相信我的话:
输出量:
注意排除了垂直选项卡,但这在v5.18中得到了解决。
在过于苛刻地反对之前,Perl文档使用了相同的技术。perlrecharclass的“空白”部分中的一个脚注是这样的:
在Perl v5.18之前,
\s
与垂直选项卡不匹配。[^\S\cK]
(模糊地)与\s
传统上所做的相匹配。Unicode属性
前面提到的关于
\h
和\H
的perlre文档引用了perlunicode文档,我们在那里读到了一系列有用的Unicode属性。\p{Blank}
\h
和\p{HorizSpace}
相同:水平改变间距的字符。\p{HorizSpace}
\h
和\p{Blank}
相同:水平改变间距的字符。直接方式:ASCII版本
perlrecharclass的“空白”部分还建议了其他一些方法,这些方法不会冒犯语法老师对双重否定的反对。
说出你想要的而不是你不想要的。
在区域设置和Unicode规则之外,或者当
/a
或/aa
开关生效时,“\s
匹配[\t\n\f\r ]
,并且从Perl v5.18开始,垂直制表符\cK
”。要匹配空格而不匹配换行符(广义上),请丢弃
\r
和\n
以保留直接方式:Unicode版本
如果您的文本是Unicode,请使用与下面的sub类似的代码从perlrecharclass的“Whitespace”部分的表中构造一个模式。
以上是为了完整性。使用Unicode属性,而不是手写。
其他应用
双重否定的技巧对于匹配字母字符也很方便。请记住,
\w
匹配“单词字符”、字母字符 * 和 * 数字以及下划线。我们丑陋的美国人有时想把它写成,比如说,但双重否定字符类可以尊重区域设置:
用这种方式表示“一个单词字符,而不是数字或下划线”有点不透明。POSIX字符类更直接地传达意图
或者使用szbalint建议的Unicode属性
Pingui询问有关嵌套双重否定字符类以有效修改
我能想到的最好的方法是使用
|
作为替代,并将\s
移动到另一个分支:ctzwtxfj2#
perl5.10和更高版本支持辅助的垂直和水平字符类
\v
和\h
,以及通用的空白字符类\s
最干净的解决方案是使用 horizontal whitespace 字符类
\h
。这将匹配ASCII集合中的制表符和空格、扩展ASCII中的不间断空格或任何这些Unicode字符\v
不太有用,但可以匹配以下字符有7个垂直空格字符匹配
\v
,18个水平空格字符匹配\h
。\s
匹配23个字符所有空白字符都是 * 垂直 * 或 * 水平 *,没有重叠,但它们不是真子集,因为
\h
还匹配U+00 A0 NO-BREAK SPACE,\v
还匹配U+0085 NEXT LINE,\s
不匹配这两个字符jaxagkaj3#
Greg’s answer的一个变体,也包括回车:
这个正则表达式比没有
\r
的/[^\S\n]/
更安全。我的理由是,Windows使用\r\n
作为换行符,Mac OS 9使用\r
。现在你不太可能找到不带\n
的\r
,但是如果你找到了,它只意味着一个换行符。因此,由于\r
可以表示换行符,我们也应该排除它。yjghlzjz4#
下面的正则表达式将匹配白色空格,但不匹配新行字符。
DEMO
如果你还想添加回车符,那么在负的lookahead中添加
|
和|
运算符。DEMO
在非捕获组之后添加
+
,以匹配一个或多个白色空格。DEMO
我不知道为什么你们没有提到POSIX字符类
[[:blank:]]
,它匹配任何水平空格(* 空格和制表符 *)。这个POSIX字符类可以在BRE(Basic Regular Expressions),ERE(Extended Regular Expression),PCRE(Perl Compatible Regular Expression)上工作。DEMO
4urapxun5#
您正在寻找的是POSIX
blank
字符类。在Perl中,它被引用为:在Java中(不要忘记启用
UNICODE_CHARACTER_CLASS
):与类似的
\h
相比,POSIXblank
被更多的正则表达式引擎(reference)支持。一个主要的好处是其定义固定在附件C中:Unicode正则表达式和所有支持Unicode的正则表达式的标准的兼容性属性。(例如,在Perl中,\h
选择额外包含MONGOLIAN VOWEL SEPARATOR
。)然而,支持\h
的一个论点是它总是检测Unicode字符(即使引擎不同意),而POSIX字符类通常默认仅用于ASCII(如Java中)。但问题是,即使坚持Unicode也不能100%解决这个问题。考虑以下在Unicode中不被视为空白的字符:
来源:https://en.wikipedia.org/wiki/White-space_character
前面提到的蒙古语元音分隔符没有包括在内,这可能是一个很好的理由。它与200 C和200 D一起沿着出现在单词(AFAIK)中,因此打破了所有其他空白都遵守的基本规则:你可以用它来标记。它们更像是修饰语。但是,
ZERO WIDTH SPACE
、WORD JOINER
和ZERO WIDTH NON-BREAKING SPACE
(如果它不是用作字节顺序标记)符合我书中的空白规则。因此,我将它们包含在水平空白字符类中。在Java中:
00jrzges6#
将下面的正则表达式放在 find 部分,并从“Search Mode”中选择 Regular Expression:
eoxn13cs7#
你可能想要
\h
,就像其他人指出的那样。但是,Perl v5.18 and later supports regex set operations作为其Unicode支持的一部分。如果你想要某样东西的大部分,减去你不想要的那几样东西可能更容易。假设您接受除了换行符之外的任何空格。你不关心回车、换页或者垂直制表符。这个正则表达式集合操作通过从所有空格开始并删除换行符来创建一个字符类:
还有一个假设你想要所有的拉丁字母除了元音。你可以把它和遗漏写出来,希望你不会出错:
当代码清楚地显示您正在做的事情时,这会更容易:
eni9jsuy8#
m/ /g
只是在/ /
中给给予空间,它就能工作。或者使用\S
-它将替换所有特殊字符,如制表符,换行符,空格等。