空白を一致させたいけれど、改行を一致させたくない場合があります。
これまでは に頼ってきました[ \t]
。もっと気まずくない方法はないでしょうか?
ベストアンサー1
まとめ
- 多くの非ペクレエンジンでは二重否定を使用します。
[^\S\r\n]
- ASCII を扱う場合は、何が欲しいかを述べてください。
[\t\f\cK ]
- 水平方向の空白スペースに一致させるために使用します
\h
。Perl v5.10.0以降(2007年公開) - Unicodeプロパティ:
\p{Blank}
または\p{HorizSpace}
- Unicode で何を望んでいるのかを明確にする(ただし、実際にはそうする必要はありません)
- 二重否定とUnicodeプロパティのその他の使用法
二重否定
パターンを他のエンジン、特にPerl互換または をサポートしない場合は\h
、二重否定として表現します。
[^\S\r\n]
つまり、空白文字ではない(大文字のS
補完)か、改行文字ではない、または改行文字ではないということです。外側のnot(つまり、^
括弧付き文字クラス) とド・モルガンの法則は、から\r
とを減算するのと同じです。パターンに復帰と改行の両方を含めると、Unix (LF)、クラシックMac OS (CR)、DOS風 (CRLF) のすべてを正しく処理できます。\n
\s
改行規則。
私の言うことを信じる必要はありません。
#! /usr/bin/env perl
use strict;
use warnings;
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" => 一致なし
垂直タブが除外されていることに注意してください。これはv5.18で対処。
あまり厳しく反論する前に、Perlのドキュメントでも同じ手法が使われている。perlrecharclass の「空白」セクション読む
Perl v5.18 より前では、
\s
垂直タブと一致しませんでした。[^\S\cK]
(あいまいですが)\s
従来のものと一致。
直接的なアプローチ: ASCII 版
のperlrecharclass の「空白」セクションまた、二重否定に反対する文法教師を怒らせない他のアプローチも提案しています。
言いたくないことよりも、言いたいことを言いましょう。
ロケールとUnicodeのルール外の場合、または/a
または/aa
スイッチが有効になっている場合、「 」\s
は[\t\n\f\r ]
、Perl v5.18 以降では垂直タブ\cK
」に一致します。
空白に一致し、改行には一致しない (広義) 場合は、 を破棄して\r
を残し\n
ます[\t\f\cK ]
。
水平方向の空白
のperlre の「文字クラスとその他の特別なエスケープ」セクション含まれるもの
\h
水平方向の空白\H
水平方向の空白ではない
Unicode プロパティ
前述のperlreドキュメント\h
と\H
を参照するperlunicode ドキュメントここでは、便利な Unicode プロパティのファミリーについて説明します。
\p{Blank}
\h
これはおよびと同じです\p{HorizSpace}
。水平方向の間隔を変更する文字です。\p{HorizSpace}
\h
これはおよびと同じです\p{Blank}
。水平方向の間隔を変更する文字です。
直接的なアプローチ: Unicode 版
テキストがUnicodeの場合は、以下のサブのようなコードを使用して、表からパターンを構築します。perlrecharclass の「空白」セクション。
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;
}
上記は完全性を保つためのものです。手書きで書くのではなく、Unicode プロパティを使用してください。
二重否定と Unicode プロパティのその他の応用
二重否定のトリックは、アルファベット文字の一致にも便利です。\w
単語文字、アルファベット文字、数字、アンダースコアに一致することを覚えておいてください。私たち醜いアメリカ人は、次のように書きたくなることがあります。
if (/[A-Za-z]+/) { ... }
ただし、二重否定の文字クラスはロケールを尊重できます。
if (/[^\W\d_]+/) { ... }
このように「単語文字だが数字やアンダースコアではない」と表現するのは少しわかりにくい。POSIX文字クラスは、より直接的に意図を伝えます。
if (/[[:alpha:]]+/) { ... }
またはUnicodeプロパティでシュバリント提案された
if (/\p{Letter}+/) { ... }
ピングイ二重否定文字クラスをネストして効果的に変更する方法を尋ねた\s
。
/(\+|0|\()[\d()\s-]{6,20}\d/g
の私が思いつく限りのベスト|
代替としてを使用し、\s
他のブランチに移動します。
/(\+|0|\()(?:[\d()-]|[^\S\r\n]){6,20}\d/g