空白に一致するが改行には一致しない


277

改行ではなく空白に一致させたい場合があります。

これまでのところ、私は頼りにしてきました[ \t]。それほど厄介な方法はありませんか?


4
ところで、これらの文字も「空白」です:[\r\f]
Eugene Yarmash

2
@eugeneyはまだ誰かがフォームフィードを行っていますか?(\ f's)
アランマルホランド

1
@AranMulholland:文字指向のプリンターを持っている人。ほとんどのプリンターには、PostScriptまたはHewlett Packardインターフェースが呼び出されるものと同様に文字モードがあり、ページをスローするにはフォームフィードを送信します。
ボロディン

1
@Borodin Hewlett Packardは、PCL(Printer Control Language)と呼ばれています。
CB_Ron 2018年

回答:


182

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

一致する7つの垂直方向の空白文字と\v、18個の水平方向の空白文字が一致し\hます。\s23文字に一致

すべての空白文字は、垂直または水平で重複はありませんが、\hU + 00A0 NO-BREAK SPACEに\vも一致し、U + 0085 NEXT LINEにも一致するため、適切なサブセットではありません。\s


7
\hをサポートする言語でのみ動作しますPCRE
Avinash Raj 14

14
@AvinashRaj:この質問はPerlについてです。PerlはPCREを確実にサポートします
ボロディン

2
@AvinashRaj:それ[[:blank:]]がノーブレークスペースと一致しない場合を除いて-  または"\xA0"
Borodin

6
\hNotepad ++で1つ以上の連続する非改行スペースで検索/置換を行っていた私のユースケースでは、これが完全に機能したことに言及したいと思います。他には何も(単純な)機能しませんでした。
squidbe 2015年

8
Perlが\h少し非標準になっているのは、が含まれているためですMONGOLIAN VOWEL SEPARATOR。Unicodeは空白を考慮しません。そのため、Perl \hはPOSIX blank[[:blank:]]Perl、\p{Blank}Java)およびJava 8とは異なり\hます。確かに、それはエッジケースです。
Aleksandr Dubinsky 2016

362

ダブルネガティブを使用:

/[^\S\r\n]/

つまり、not-not-whitespace(大文字のSは補数)またはnot-carriage-returnまたはnot-newlineです。アウターnot(つまり^文字クラスでの補完)をドモーガンの法則で分配すると、これは「空白文字ですが、キャリッジリターンや改行ではありません」と同等です。パターンとパターンの両方\rを含めると\n、すべてのUnix(LF)、クラシックMac OS(CR)、およびDOS風(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";
}

出力:

"" =>一致
"\ f" =>一致
"\ t" =>一致
"\ r" =>一致しません
"\ n" =>一致しません

垂直タブの除外に注意してください。ただし、これはv5.18対処されています

厳しく反対する前に、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}+/) { ... }

4
賢いですが、その振る舞いは非常に驚くべきものであり、それがいかに扱いにくいかはわかりません。
Qwertie 2010

7
@Qwertie:驚くべきことは何ですか?何よりも厄介ですか?
10

9
ひどいひどい。

9
これはとても良いです。リクエストに応じて、(一部の空白文字だけでなく)空白を照合し、改行文字を除外します。あなたの解決策は、それがすべきではないので、「空白文字が何であるか」という質問には関係しません。これがまさに私が探していたものです。(@Roryで述べたように、「改行」には\rWindowsなども含まれる可能性があるため、マッチから除外することも検討してください/[^\S\r\n]/
Timo

1
これは確実にOPのニーズと、この質問を検索する事実上すべての人(とにかく英語を話す人)のニーズを満たします。しかし、それはまだ悪い答えです。が\h利用可能な場合、このソリューションを使用するための言い訳はありません。
アランムーア

50

キャリッジリターンも含むグレッグの回答のバリエーション:

/[^\S\r\n]/

この正規表現は/[^\S\n]/noを使用するよりも安全です\r。私の考えでは、Windowsは\r\n改行に使用し、Mac OS 9はに使用してい\rます。今日\rなくして見つけることはほとんどあり\nませんが、見つけたとしても、改行以外の意味はありません。したがって、\rは改行を意味する可能性があるため、それも除外する必要があります。


1
+1 グレッグの解決策は私のテキストを壊してしまいました、あなたの解決策はうまくいきました。
Timo Huovinen、2014年

行末に「\ r」を使用しているプログラムの数に驚くかもしれません。私の問題は、ファイルがこれらを使用していることであると理解するのにしばらく時間がかかることがありました。または、MacRoman文字エンコードを使用したこと
mivk

2
@Gregが最初に「間違った」変更を行ったようで、あなたにクレジットを付与しなかったようです。ここで賛成票を投じるのはそのためです。
Andre Elrico

14

以下の正規表現は空白と一致しますが、改行文字とは一致しません。

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

デモ

キャリッジリターンを追加する場合も、否定先読み内に演算子を追加\r|ます。

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

デモ

+非キャプチャグループの後に追加して、1つ以上の空白に一致させます。

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

デモ

[[:blank:]]水平方向の空白(スペースとタブ)に一致するPOSIX文字クラスに言及しなかった理由がわかりません。このPOSIX 文字クラスは、BRE(基本正規表現)、ERE(拡張正規表現)、PCRE(Perl互換正規表現)で機能します。)で機能します。

デモ


これが最善の解決策です!
loretoparisi

13

探しているのは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の空白とは見なされない以下の文字を考慮してください。

前述のモンゴル語の​​母音区切りは、おそらく正当な理由で含まれていません。これは、200Cおよび200Dとともに、単語内(AFAIK)で発生するため、他のすべての空白が従う基本的な規則に違反します。これをトークン化できます。それらは修飾子のようなものです。しかし、ZERO WIDTH SPACEWORD JOINER、およびZERO WIDTH NON-BREAKING SPACE(それがバイトオーダーマーク以外のものとして使用されている場合)、私の本の中で空白のルールに適合し。したがって、横の空白文字クラスに含めます。

Javaの場合:

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

適切な正規表現コンパイルフラグをJavaコンパイルに追加し、Java 7以降を実行している必要があります。いずれにしても、問題はJavaやPCREに関するものではなかったため、これは重要ではありません。
tchrist

@tchristこれを指摘していただきありがとうございます。回答を更新します。しかし、私の答えは無関係であることに私は同意しません。重要でないのはperl、元の質問のタグです。
Aleksandr Dubinsky 2014

1
@AleksandrDubinsky、\ p {Blank}はJavaScriptではサポートされていないため、「すべての正規表現フレーバーに標準」ではありません-1
Valentin Vasilyev

最も有益。一般的で完全な「水平空白」の省略文字クラスが存在せず、のようなホラー[\p{Blank}\u200b\u180e]が必要であることを知るのは気がかりです。確かに、母音区切り文字が空白文字と見なされないのは理にかなっていますが、なぜ\sandのようなクラスにゼロ幅のスペースがないのか\p{Blank}、私を打ち負かしています。
ティモ

フォローアップ:理由は説明されていませんが、どちらも「境界ニュートラル」と見なされていると読みました。
ティモ

-4

m/ /gでスペースを空けるだけで/ /動作します。または使用\S—タブ、改行、スペースなどのすべての特殊文字を置き換えます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.