空白ではなく改行に一致させたい場合があります。
これまで、私は[ \t]
に頼ってきました。それほど厄介な方法はありますか?
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
に一致する7個の垂直方向の空白文字と、\h
に一致する18個の水平方向の空白文字があります。 \s
は23文字に一致します
すべての空白文字はverticalまたはhorizontalのいずれかですが、\h
もU + 00A0 NO-BREAK SPACEに一致し、\v
もU +に一致するため、適切なサブセットではありません0085 NEXT LINE、どちらも\s
に一致しない
二重否定を使用します。
/[^\S\r\n]/
つまり、空白ではない(大文字のSが補う)またはキャリッジリターンではない、または改行ではない。 De Morganの法則 で外側のnot(ie、文字クラスの^
を補完する)を配布するパターンに\r
と\n
の両方を含めると、Unix(LF)、従来のMac OS(CR)、DOS-ish( CR LF) 改行規則 。
私の言葉を受け入れる必要はありません:
#! /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";
}
出力:
"" => match "\ f" => match "\ t" => match "\ r" => no match "\ n "=>一致なし
垂直タブが除外されていることに注意してください。ただし、これは v5.18で対応 です。
厳しく反対する前に、Perlのドキュメントは同じテクニックを使用しています。 perlrecharclassの「Whitespace」セクション の脚注
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}+/) { ... }
Gregの答え のバリエーションには、キャリッジリターンも含まれます。
/[^\S\r\n]/
この正規表現は、/[^\S\n]/
を持たない\r
よりも安全です。私の推論では、Windowsは改行に\r\n
を使用し、Mac OS 9は\r
を使用したということです。最近、\r
なしで\n
を見つけることはほとんどありませんが、それを見つけたとしても、改行以外の意味はありません。したがって、\r
は改行を意味する可能性があるため、これも除外する必要があります。
探しているのはPOSIX blank
文字クラスです。 Perlでは、次のように参照されます。
[[:blank:]]
Java(UNICODE_CHARACTER_CLASS
を有効にすることを忘れないでください):
\p{Blank}
類似の\h
と比較して、POSIX blank
は、さらにいくつかの正規表現エンジンでサポートされています( reference )。主な利点は、その定義が 付録C:Unicode正規表現の互換性プロパティ に固定されており、Unicodeをサポートするすべての正規表現フレーバーの標準であることです。 (例えばPerlでは、\h
はMONGOLIAN VOWEL SEPARATOR
を追加することを選択します。)ただし、\h
を支持する引数は、Unicode文字を常に検出することです(エンジンがどちらに同意しなくても)デフォルトではASCIIのみ(Javaのように)。
しかし問題は、ユニコードに固執しても問題を100%解決できないことです。 Unicodeで空白と見なされない次の文字を考慮してください。
U + FEFF ZERO WIDTH非破壊スペース
前述のモンゴル語の母音セパレータは、おそらく正当な理由のために含まれていません。これは、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]"
以下の正規表現は空白文字に一致しますが、改行文字には一致しません。
(?:(?!\n)\s)
キャリッジリターンも追加する場合は、負の先読み内で\r
演算子を使用して|
を追加します。
(?:(?![\n\r])\s)
非キャプチャグループの後に+
を追加して、1つ以上の空白に一致させます。
(?:(?![\n\r])\s)+
水平方向の空白(のスペースとタブ)に一致するPOSIX文字クラス[[:blank:]]
について言及しなかった理由がわかりません。このPOSIX特性クラスは、BRE(Basic REgular Expressions)、ERE(Extended Regular Expression)、PCRE(Perl互換正規表現)。