何にもマッチしない正規表現


131

これは馬鹿げた質問のように聞こえるかもしれませんが、私は私の仲間の開発者の何人かと長い話し合いをしました、そしてそれは考えるのは楽しいことのように聞こえました。

そう; あなたの考えは何ですか-正規表現はどのように見えますか?

編集:なぜこれが必要なのですか?1つは、そのような表現について考えるのが興味深いためです。2つ目は、スクリプトに必要なためです。

そのスクリプトでは、辞書をと定義していDictionary<string, Regex>ます。これには、ご覧のとおり、文字列と式が含まれています。

そのディクショナリーに基づいて、私はすべてこのディクショナリーを使用してメソッドを作成する方法の参照としてのみ使用するメソッドを作成します。そのうちの1つは、正規表現を解析済みログファイルと照合します。

式が一致する場合、式Dictionary<string, long>によって返される値に別の値が追加されます。そこで、辞書の表現と一致しないログメッセージをキャッチするために、「不明」という新しいグループを作成しました。

このグループには、他のものと一致しなかったすべてが追加されます。しかし、「未知の」式が(偶然に)ログメッセージと一致しないようにするために、どの文字列を指定しても、決して一致しない式を作成する必要がありました。

したがって、あなたにはこの「本当の質問ではない」という私の理由があります...


1
ネガティブを証明することは非常に難しいことに注意してください。
Lasse V. Karlsen、

5
面白い。あなたはそのような正規表現をどこで使いますか?
チャーリーソルト

1
上記のコメントの多くとこの質問への回答は、もともとstackoverflow.com/questions/1845078/…からのものであるという記録のために、ここで書き留めておきます。Marc Gravellはそれらをマージしました。これにより、これらの応答の多くは、正確な元のコンテキストがなければ、奇妙なものになり、いくつかのコメントが意味をなさないように見えます。(おそらく、将来の潜在的な担当者ポイントも盗みます。)このような詳細な背景を持つ質問は、「正確な重複」にはなり得ないことをお勧めします。何でも...
ピーターハンセン

2
この質問は、「Advanced Regex-Fu」の下のStack Overflow Regular Expressions FAQに追加されました。
aliteralmind 2014

3
「ネガティブを証明することは非常に難しいことに注意してください」-これは広く信じられていますが、完全かつ明らかに誤りです...少なくともユークリッドが最高の素数がないことを証明して以来、私たちは知っています。そして、Pの証明は(Pではなく)の否定の証明です。真実であることは、「すべてのワタリガラスが黒である」や「すべてのワタリガラスが白ではない」など、実証的または否定的な経験的普遍性を証明することは難しいということです。アルゴリズムは経験的なものではなく分析的なものであるため、これは偽のルールの特に悪い誤用です。たとえば、パターン 'a'が 'b'で始まる文字列と一致しないという証明は「非常に困難」ではありません。
ジムBalter

回答:


66

これは実際には非常に単純ですが、実装/フラグによって異なります *:

$a

a文字列の末尾の後の文字と一致します。幸運を。

警告:
この式は負荷が高く、行全体をスキャンして行末のアンカーを検出しますが、その後のみを検出しaて否定的な一致を返します。(詳細については、下のコメントを参照してください。)


*元々、マルチラインモードの正規表現についてはあまり考えていませんでした$が、行の終わりにも一致します。実際、これは改行の直前の空の文字列に一致するため、などの通常の文字aはの後に表示できません$


50
この式は負荷が高く、行全体をスキャンして行末のアンカーを見つけ、 "a"を見つけて否定的な一致を返すだけです。〜275kの行ファイルをスキャンするのに〜480msかかることがわかりました。逆の "a ^"は、より効率的に見える場合でも、ほぼ同じ時間がかかります。一方、負の先読みでは何もスキャンする必要はありません。「(?! x)x」(xの後にxも続かないもの、つまり何もないもの)は約30msかかり、時間の7%未満です。(
GNU

1
Perlでは、の現在の値と一致します$a。また、Perlに相当するもの$(?:a)は非常に低速perl -Mre=debug -e'$_=a x 50; /$(?:a)/'です。
ブラッド・ギルバート

@arantiusは、参照してください。タイミングに関する私の答えを私はして測定正反対のを発見したとして、timeitpython3
nivk

6年間とPythonのメジャーバージョンが状況を変える可能性があることは衝撃的ではありません。
アランティウス2017年

1
POSIX BRE構文で$aは、はそのパターンのアンカーとして無効$aであるため、リテラルテキストと一致します$
phils '26

76

レバレッジnegative lookahead

>>> import re
>>> x=r'(?!x)x'
>>> r=re.compile(x)
>>> r.match('')
>>> r.match('x')
>>> r.match('y')

このREは矛盾しているため、何にも一致しません。

注:
Pythonでは、re.match()は暗黙的\Aに正規表現の先頭に文字列の先頭のアンカー()を追加します。このアンカーはパフォーマンスにとって重要です。アンカーがないと、文字列全体がスキャンされます。Pythonを使用しない場合は、アンカーを明示的に追加する必要があります。

\A(?!x)x

@ Chris、yep-また、(?=x)(?!x)その他(矛盾する先読みの連結、および後読みについても同じ)、それらの多くは、任意の値に対しても機能しますx(後読みにxは、固定長の文字列と一致するsが必要です)。
Alex Martelli、

1
うまく機能しているようです。しかし、代わりに(?!)()は常に一致するため、(?!)が一致しないことが保証されないのではないですか?
Peter Hansen、

2
@ピーター、はい、Pythonがその構文を受け入れた場合(そして最近のリリースではそうであるように見える場合)、それも自己矛盾します。別のアイデア(それほどエレガントではありませんが、関心のあるすべてのREエンジンで機能するものを見つけると、より可能性が高くなります)r'a\bc':、両側の文字ですぐに囲まれた単語境界を探します(バリアント:非単語文字両側)。
Alex Martelli、

1
おもしろいことに、入力で「認識」しない単純なリテラルを使用したオリジナルは、Pythonで最も高速であることがわかりました。5MBの入力文字列を使用し、これをsub()操作で使用すると、(?! x)xは21%長く、(?!())は16%、($ ^)は6%長くなります。私の場合ではないが、いくつかのケースでは重要かもしれません。
Peter Hansen、

2
それはかなり遅くなる可能性がありますperl -Mre=debug -e'$_=x x 8; /(?!x)x/'。最初\A(?!x)xまたは最後にアンカーすることで、より速くすることができ(?!x)x\zます。perl -Mre=debug -e'$_=x x 8; /(?!x)x\z/; /\A(?!x)x/'
ブラッド・ギルバート

43

逃したもの:

^\b$

空の文字列には単語の境界が含まれていないため、一致できません。Python 2.5でテストされています。


7
これが最良の答えです。先読みを使用せず、一部の正規表現の実装で破損せず、特定の文字(「a」など)を使用せず、全体をスキャンせずに最大3つの処理ステップ(regex101.comによる)で失敗する入力文字列。これも一目でわかりやすいです。
CubicleSoft 2016年

1
これは実際には特定の条件でEmacsで失敗します(バッファーの先頭または末尾に空白行がある場合)が\`\b\'機能し、「開始/終了」ではなく「開始/終了」の代わりにEmacs構文を使用します行の」)。
phils '26

35

見回す:

(?=a)b

正規表現の初心者の場合:前向きな前向き(?=a)a、次の文字がであることを確認しますが、検索場所を変更しません(または一致した文字列に「a」を含めません)。次の文字が確認されたのでa、正規表現(b)の残りの部分は、次の文字が一致する場合にのみ一致しbます。したがって、この正規表現は、文字が両方ある場合のみ一致しますab同時に。


30

a\bc\bは、単語の境界に一致するゼロ幅の式です。

単語の途中に表示することはできません。


ユースケースでパターンを文字列の先頭に固定できる場合、その拡張により、正規表現エンジンaはテキスト内ののすべてのインスタンスを検索およびテストできなくなります。
phils '26

20

$.

.^

$.^

(?!)


1
可愛い!最初の3つのようなアイデアは「違法」なので、私の潜在意識は私をそらしました...概念的には、しかし正規表現には明らかに関係ありません。私は(!)1つを認識しません...それを調べる必要があります。
Peter Hansen

1
さて、私は(?!)答えが好きです...アレックスが提案した事実 stackoverflow.com/questions/1723182(上記のAmarghoshが指摘)では、誰かが正規表現の「一部のフレーバー」が構文エラーと見なすと主張していることに注意してください。Pythonはそれでも大丈夫です。他の提案はすべてPythonのre.DOTALL | re.MULTILINEモードで失敗することに注意してください。
Peter Hansen、

1
これはテストされましたか?正規表現が複数行の式である場合を除き、正規表現^の最初の文字として特別な意味しかなく、正規表現$の末尾でのみ特別な意味があると思いました。
PP。

実際、Perlでの/$./意味はまったく異なります。$.(入力行番号)の現在の値と一致することを意味します。/$(.)/あなたがuse re '/s';それの前に書けば、何かと一致することさえできます。(perl -E'say "\n" =~ /$(.)/s || 0'
ブラッド・ギルバート

POSIX BREの構文では、^$最初と最後にだけ特別です(それぞれ)のパターンのため、のいずれ$..^またはが$.^動作しないでしょう。 (?!)Perl / PCREの機能だと思います。
phils '26

13

最大マッチング

a++a

バックトラックなしで、少なくとも1つのa後に任意の数のが続きaます。次に、もう1つ一致させてくださいa

または独立した部分式

これはa+、独立したサブ式の後に別のを置くのと同じaです。

(?>a+)a

10

Perl 5.10は、「動詞」と呼ばれる特別な制御語をサポートしてい(*...)ます。これは、順番に囲まれています。((?...)特別なシーケンスと比較してください。)その中に、動詞が含まれてい(*FAIL)ます正規表現からすぐに戻るがいます。

動詞はまもなくPCREにも実装されるので、PCREライブラリを使用してPHPや他の言語でも使用できます。(ただし、PythonやRubyでは使用できません。独自のエンジンを使用します。)


perldoc.perl.org/perlre.html#%28%2AFAIL%29-%28%2AF%29にあるそのためのドキュメントには、「このパターンは何にも一致せず、常に失敗します。これは(?!)と同等ですが、簡単に実際には、(?!)は内部で(* FAIL)に最適化されます。(?!)はこれまでのところ私のお気に入りの「純粋な」回答です(JavaScriptでは機能しませんが)。ありがとう。
Peter Hansen、

10
\B\b

\b 単語の境界に一致-文字と非文字の間の位置(または文字列の境界)。
\B2つの文字間または非文字間の位置に一致します。

一緒にそれらはどの位置にも一致しません。

以下も参照してください。


これは、優れたソリューションのように思える提供、それが特定のポイント(テキストの先頭が賢明と思われる)に固定されます。あなたがそれをしないなら、それはひどい解決策です、なぜならそれはテキストのすべての非単語境界が単語境界が続いているかどうかを確かめるためにテストされるからです!したがって、賢明なバージョンは次のようになり^\B\bます。「テキストの先頭」と「行の先頭」の構文が異なる言語では、「テキストの先頭」構文を使用する必要があります。そうしないと、すべての行がテストされます。(たとえば、Emacsでは、これは\`\B\bor "\\`\\B\\b"です。)
phils '26

とは言っても、この質問の目的はグループで使用するための正規表現を取得することであることに注意しました。この場合^、特定の正規表現構文(POSIX BREなど)では^、最初の文字がアンカーである場合にのみ問題があります。パターンの場合、それ以外の場合はリテラル^文字と一致します。
phils '26

@phils-私はあなたがそれを考えすぎていると思います:)-これは非現実的な質問であり、目的は興味深い答えを見つけることでした-効率的な答えではありません。とは言っても、パターンは(ターゲット文字列のサイズによって)ライナータイムで拒否される可能性があるため、正規表現^に問題はありません。ここでのほとんどのパターンは同じであり、最適化されていなければ線形である可能性もあります。
コビ

再:最適化、私は他の位置で「テキストの始まり」を見つけることを期待している正規表現エンジンを無視してもかまいません:)
phils '26

また、それほど実用的ではないQ&Aでもありません-ここで私が結んだ唯一の理由は、正規表現値を必要とする特定のEmacs変数を構成するという実用的な目的のために、誰かが自分自身に対してより効率的なソリューションを提案できるかどうかを確認することでした効果的に無効にしたかった。
phils '26

8

これはうまくいくようです:

$.

2
これは、Ferdinand Beyerの例に似ています。
ガンボ

9
そして、それはdot-matches-newlinesモードで一致します。
Tim Pietzcker、2009年

Perlでは、現在の入力行番号と実際に一致し$.ます。その場合は、$(.)同等以上の手段を講じる必要があります$(?:.)
ブラッド・ギルバート

POSIX BRE構文で$.は、はそのパターンのアンカーとしては無効$であるため、任意の文字が後に続くリテラルと一致$します。
phils '26

8

どの程度$^か、多分(?!)? 


3
改行は、行の^先頭と$末尾に一致するモードでこの式と一致します。
ガンボ

4
多分彼は意味した(?!)-空の文字列の否定先読み。しかし、一部の正規表現フレーバーは、これも構文エラーとして扱います。
アランムーア

1
空の文字列は、少なくともJavaScriptでは最初のものと一致します。
Roland Pihlakas、2015年

POSIX BRE構文で$^は、これらのリテラル文字に一致します。これは、文字がアンカーとして無効であるためです(つまり、パターンを使用したために、パターンが
意図したとおりに機能

5

最速は:

r = re.compile(r'a^')
r.match('whatever')

「a」には、特殊文字以外の文字(「x」、「y」)を使用できます。Knioの実装は少し純粋かもしれませんが、「a」の代わりに選択した文字で始まらないすべての文字列の方が高速です。これらの場合、最初の文字の後ではなく、最初の文字の後に一致しないためです。


実際、私の場合、(。^)は(\ x00 ^)よりも約10%遅くなります。
Peter Hansen、

1
\ n以外の値を使用すると文字が一致しないことが保証されるため、これを受け入れます。(?! x)xオプションよりも少し読みやすい(正規表現の専門家が比較的少ないという前提で)と考えています。 、私もその1つに投票しました。私の場合、どちらのオプションについても、それを説明するためのコメントが必要になるので、元の試みを '\ x00NEVERMATCHES ^'に調整すると思います。私はこの答えが一致しないことを保証します。私の元の自己文書化の強さで。答えてくれてありがとう!
Peter Hansen、

3
これは実際に機能しますか?機能する場合、Unixで中断することに決めたのは誰ですか?Unixの正規表現で^は、は最初の文字としてのみ特殊で、と同様$です。どのUnixツールでも、その正規表現はリテラル文字列を含むすべてのものと一致しますa^
JaakkoK、2009

ええ、それは良い攻撃です。そのリテラル文字列に対してテストしたことはありません。
Adam Nelson、

ああ、それがUnixの正規表現を破ったら、きっと気に入るはずです>^
CubicleSoft 2016年

4

Pythonはそれを受け入れませんが、Perlは次のことを行います。

perl -ne 'print if /(w\1w)/'

w最初のグループ(()s)はそれ自体に再帰するため、この正規表現は(理論的には)sの無限(偶数)数に一致しようとする必要があります。Perlは、の下use strict; use warnings;でも警告を発行していないようです。そのため、それは少なくとも有効であり、私の(最小限の)テストは何にも一致しないため、あなたの批評のために提出します。


1
理論は常にいいですが、実際には「無限」という言葉を含む正規表現が心配になると思います。
Peter Hansen、

perl -Mre=debug -e'"www wwww wwwww wwwwww" =~ /(w\1w)/'
ブラッド・ギルバート

@BradGilbert-これをここで実行すると(5.10、少し古い)、OPが要求したとおり「正規表現の失敗」が発生します。それはあなたのシステムに一致しますか?
Chris Lutz


4

これはPythonや他の多くの言語では機能しませんが、Javascriptの正規表現で[]は一致しない有効な文字クラスです。そのため、入力が何であっても、以下はすぐに失敗するはずです。

var noMatch = /^[]/;

私はそれよりも好きです /$a/意図が明確に伝わっているので、自分です。そして、いつそれが必要になるかについては、ユーザー入力に基づいて動的にコンパイルされたパターンのフォールバックが必要だったので、それが必要でした。パターンが無効な場合は、何にも一致しないパターンに置き換える必要があります。簡略化すると、次のようになります。

try {
    var matchPattern = new RegExp(someUserInput);
}
catch (e) {
    matchPattern = noMatch;
}

4

境界マッチャーを含むすべての例は、同じレシピに従います。レシピ:

  1. 境界マッチャーのいずれかを取る:^、$、\ b、\ A、\ Z、\ z

  2. 彼らが意図されているものとは反対にしてください

例:

^と\ Aは最初のものなので、最初に使用しないでください

^ --> .^
\A --> .\A

\ bは単語の境界に一致するので、その間に使用します

\b --> .\b.

$、\ Z、\ zは最後に使用するため、最後に使用しないでください

$ --> $.
\Z --> \Z.
\z --> \z.

他の人は先読みと後読みの使用を伴いますが、これも同じように機能します。正または負の先読みに続いて反対の何かを与える場合

(?=x)[^x]
(?!x)x

あなたが反対の何かに続いてポジティブまたはネガティブ後見をするなら

[^x](?<=x)
x(?<!x)

それらはよりそのようなパターンとより多くのそのような類推である可能性があります。


3

とても良い答えがたくさん!

@nivkの回答と同様に、一致しない正規表現のさまざまなバリアントに対するPerlのパフォーマンス比較を共有したいと思います。

  1. 入力:疑似ランダムASCII文字列(25,000行、長さ8〜16):

正規表現の速度:

Total for   \A(?!x)x: 69.675450 s, 1435225 lines/s
Total for       a\bc: 71.164469 s, 1405195 lines/s
Total for    (?>a+)a: 71.218324 s, 1404133 lines/s
Total for       a++a: 71.331362 s, 1401907 lines/s
Total for         $a: 72.567302 s, 1378031 lines/s
Total for     (?=a)b: 72.842308 s, 1372828 lines/s
Total for     (?!x)x: 72.948911 s, 1370822 lines/s
Total for       ^\b$: 79.417197 s, 1259173 lines/s
Total for         $.: 88.727839 s, 1127041 lines/s
Total for       (?!): 111.272815 s, 898692 lines/s
Total for         .^: 115.298849 s, 867311 lines/s
Total for    (*FAIL): 350.409864 s, 285380 lines/s
  1. 入力:/ usr / share / dict / words(100,000英単語)。

正規表現の速度:

Total for   \A(?!x)x: 128.336729 s, 1564805 lines/s
Total for     (?!x)x: 132.138544 s, 1519783 lines/s
Total for       a++a: 133.144501 s, 1508301 lines/s
Total for    (?>a+)a: 133.394062 s, 1505479 lines/s
Total for       a\bc: 134.643127 s, 1491513 lines/s
Total for     (?=a)b: 137.877110 s, 1456528 lines/s
Total for         $a: 152.215523 s, 1319326 lines/s
Total for       ^\b$: 153.727954 s, 1306346 lines/s
Total for         $.: 170.780654 s, 1175906 lines/s
Total for       (?!): 209.800379 s, 957205 lines/s
Total for         .^: 217.943800 s, 921439 lines/s
Total for    (*FAIL): 661.598302 s, 303540 lines/s

(Intel i5-3320MのUbuntu、Linuxカーネル4.13、Perl 5.26)


ここでカバーされているいくつかのメソッドのJavaScript比較を次に示し
that

2

私は信じている

\Z RE FAILS! \A

正規表現にMULTILINE、DOTALLなどのフラグが含まれている場合もカバーしています。

>>> import re
>>> x=re.compile(r"\Z RE FAILS! \A")
>>> x.match('')
>>> x.match(' RE FAILS! ')
>>>

私は信じている(しかし、私はそれをベンチマークしていない)の間の文字列の長さは何でも(> 0)ということ\Z\A、故障までの時間が一定でなければなりません。


2
(*FAIL)

または

(*F)

PCREとPERLを使用すると、パターンを即座に失敗させるこのバックトラッキング制御動詞を使用できます。


2

これらの偉大な答えのいくつかを見た後、@ arantiusさんのコメント(タイミングに関する$xx^(?!x)x現在受け入れ答えには)私は時間をこれまでのソリューションの一部を望んで作られました。

@arantiusの275kライン標準を使用して、Python(v3.5.2、IPython 6.2.1)で次のテストを実行しました。

TL; DR:'x^'そして'x\by'、少なくとも〜16倍の最速であり、@ arantiusの発見とは逆に(?!x)x最も遅い(〜37 倍遅い)の1つでした。したがって、速度の問題は確かに実装に依存しています。速度が重要な場合は、コミットする前に目的のシステムで自分でテストしてください。

更新:タイミング'x^'との間には明らかに大きな不一致があり'a^'ます。詳細についてはこの質問を参照しください。a代わりにを使用した場合のより遅いタイミングについては、前の編集を参照しくださいx

In [1]: import re

In [2]: with open('/tmp/longfile.txt') as f:
   ...:     longfile = f.read()
   ...:     

In [3]: len(re.findall('\n',longfile))
Out[3]: 275000

In [4]: len(longfile)
Out[4]: 24733175

In [5]: for regex in ('x^','.^','$x','$.','$x^','$.^','$^','(?!x)x','(?!)','(?=x)y','(?=x)(?!x)',r'x\by',r'x\bx',r'^\b$'
    ...: ,r'\B\b',r'\ZNEVERMATCH\A',r'\Z\A'):
    ...:     print('-'*72)
    ...:     print(regex)
    ...:     %timeit re.search(regex,longfile)
    ...:     
------------------------------------------------------------------------
x^
6.98 ms ± 58.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
------------------------------------------------------------------------
.^
155 ms ± 960 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
------------------------------------------------------------------------
$x
111 ms ± 2.12 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
------------------------------------------------------------------------
$.
111 ms ± 1.76 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
------------------------------------------------------------------------
$x^
112 ms ± 1.14 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
------------------------------------------------------------------------
$.^
113 ms ± 1.44 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
------------------------------------------------------------------------
$^
111 ms ± 839 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
------------------------------------------------------------------------
(?!x)x
257 ms ± 5.03 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
------------------------------------------------------------------------
(?!)
203 ms ± 1.56 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
------------------------------------------------------------------------
(?=x)y
204 ms ± 4.84 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
------------------------------------------------------------------------
(?=x)(?!x)
210 ms ± 1.66 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
------------------------------------------------------------------------
x\by
7.41 ms ± 122 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
------------------------------------------------------------------------
x\bx
7.42 ms ± 110 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
------------------------------------------------------------------------
^\b$
108 ms ± 1.05 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
------------------------------------------------------------------------
\B\b
387 ms ± 5.77 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
------------------------------------------------------------------------
\ZNEVERMATCH\A
112 ms ± 1.52 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
------------------------------------------------------------------------
\Z\A
112 ms ± 1.38 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

初めてこれを実行したとき、r最後の3つの式をawするのを忘れていたため、バックスペース文字'\b'として解釈されました'\x08'。しかし、驚いたことに、'a\x08c'以前の最速結果よりも速かったです!公平を期すために、それはまだそのテキストと一致しますが、なぜそれがより速いかわからないので、それはまだ注目に値するものだと思いました。

In [6]: for regex in ('x\by','x\bx','^\b$','\B\b'):
    ...:     print('-'*72)
    ...:     print(regex, repr(regex))
    ...:     %timeit re.search(regex,longfile)
    ...:     print(re.search(regex,longfile))
    ...:     
------------------------------------------------------------------------
y 'x\x08y'
5.32 ms ± 46.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
None
------------------------------------------------------------------------
x 'x\x08x'
5.34 ms ± 66.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
None
------------------------------------------------------------------------
$ '^\x08$'
122 ms ± 1.05 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
None
------------------------------------------------------------------------
\ '\\B\x08'
300 ms ± 4.11 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
None

私のテストファイルは、「... Readable Contents And No Duplicate Lines」(Ubuntu 16.04)の式を使用して作成されました。

$ ruby -e 'a=STDIN.readlines;275000.times do;b=[];rand(20).times do; b << a[rand(a.size)].chomp end; puts b.join(" "); end' < /usr/share/dict/words > /tmp/longfile.txt

$ head -n5 /tmp/longfile.txt 
unavailable speedometer's garbling Zambia subcontracted fullbacks Belmont mantra's
pizzicatos carotids bitch Hernandez renovate leopard Knuth coarsen
Ramada flu occupies drippings peaces siroccos Bartók upside twiggier configurable perpetuates tapering pint paralyzed
vibraphone stoppered weirdest dispute clergy's getup perusal fork
nighties resurgence chafe

\B\bパフォーマンスに関してひどく欠陥があります(位置に固定されていないすべてのパターンはそうですが、このパターンは特に悪いです)。^\B\b代わりにベンチマークを試してください。
phils '26

2

空の正規表現

何にも一致しない正規表現は、空の正規表現です。しかし、すべての正規表現エンジンがそれを受け入れるかどうかはわかりません。

不可能な正規表現

他の解決策は、不可能な正規表現を作成することです。見つけた$-^だけに関係なく、あなたのテキストのサイズ(の計算するために2つのステップを取るhttps://regex101.com/r/yjcs1Z/1)。

参考のため:

  • $^ そして $.計算するために36のステップを踏む-> O(1)
  • \b\B 私のサンプルで1507ステップを取り、文字列の文字数とともに増加します-> O(n)

この質問についてのより人気のあるスレッド:


1

多分これ?

/$.+^/

Pythonでは、このアプローチは、あなたがコントロールしている場合にのみ動作フラグre.compile('$.+^', re.MULTILINE|re.DOTALL).search('a\nb\nc\n')bとc(およびすべての隣接およびイン間の改行)に対応する一致オブジェクトを返します。私が推奨する否定的先読みアプローチは、コンパイルできるフラグの任意の組み合わせで機能します(つまり、何にも一致しません)。
Alex Martelli、

私の悪い-混同$して^
Chris Lutz、

1
これは最初のに文字列の終わりを探す試みである可能性がありますが、正規表現の最後の文字でない限り、$は「文字列の終わり」を意味しないことがわかりました。これは^なので、これはリテラル$で始まりリテラル^で終わる部分文字列と一致する可能性があります
パビウム

@ pavium、PythonやJavascriptでは確かにそのようには動作しません。\でエスケープしたり、[]で文字セットに含めたりしない限り、$や^などの特殊文字はリテラルとして扱わないでください。これをどの言語で観察しましたか?
Peter Hansen、

Perlでは、少なくとも、それを書く必要があります/\z.+\A/perldoc perlreを参照)。これにより、複数行モードと単一行モード(use re '/ms')が影響を与えないようにします。
ブラッド・ギルバート

0
'[^0-9a-zA-Z...]*'

...をすべての印刷可能な記号に置き換えます;)。これはテキストファイル用です。


そのためにはもっと短い方法が必要だと思いますが、それも私の最初の考えでした^^
FP

4
これは空の文字列と一致します。すべての可能な文字をキャッチするには、[^\x00-\xFF]+(バイトベースの実装の場合)を使用します。
Ferdinand Beyer

6
より良い表現になるでしょう[^\s\S]。しかし、Ferdinand Beyerがすでに言ったように、それは空の文字列と一致します。
ガンボ

3
ドラコシャの正規表現は、次の理由により、空の文字列と一致することがあり*ます。オフのままにするか、に置き換え+ます。少なくとも1文字と一致する必要があります。クラスがすべての可能な文字を除外する場合、何にも一致しません。
アランムーア

0

正規表現の代わりに、常にfalseのifステートメントを使用するのはどうですか?JavaScriptで:

var willAlwaysFalse=false;
if(willAlwaysFalse)
{
}
else
{
}

私はチャーリーの質問に答えてコメントを追加し、なぜこのようなアプローチが望ましくないのかを説明しました。つまり、常に使用される正規表現内にグループが必要ですが、場合によっては、グループが一致しないように構築する必要があります。
Peter Hansen、

-2

正規表現の実装に依存しないポータブルソリューションは、ログメッセージに表示されないことが確実な定数文字列を使用することです。たとえば、以下に基づいて文字列を作成します。

cat /dev/urandom | hexdump | head -20
0000000 5d5d 3607 40d8 d7ab ce72 aae1 4eb3 ae47
0000010 c5e2 b9e8 910d a2d9 2eb3 fdff 6301 c85f
0000020 35d4 c282 e439 33d8 1c73 ca78 1e4d a569
0000030 8aca eb3c cbe4 aff7 d079 ca38 8831 15a5
0000040 818b 323f 0b02 caec f17f 387b 3995 88da
0000050 7b02 c80b 2d42 8087 9758 f56f b71f 0053
0000060 1501 35c9 0965 2c6e 03fe 7c6d f0ca e547
0000070 aba0 d5b6 c1d9 9bb2 fcd1 5ec7 ee9d 9963
0000080 6f0a 2c91 39c2 3587 c060 faa7 4ea4 1efd
0000090 6738 1a4c 3037 ed28 f62f 20fa 3d57 3cc0
00000a0 34f0 4bc2 3067 a1f7 9a87 086b 2876 1072
00000b0 d9e1 6b8f 5432 a60e f0f5 00b5 d9ef ed6f
00000c0 4a85 70ee 5ec4 a378 7786 927f f126 2ec2
00000d0 18c5 46fe b167 1ae6 c87c 1497 48c9 3c09
00000e0 8d09 e945 13ce 7da2 08af 1a96 c24c c022
00000f0 b051 98b3 2bf5 4d7d 5ec4 e016 a50d 355b
0000100 0e89 d9dd b153 9f0e 9a42 a51f 2d46 2435
0000110 ef35 17c2 d2aa 3cc7 e2c3 e711 d229 f108
0000120 324e 5d6a 650a d151 bc55 963f 41d3 66ee
0000130 1d8c 1fb1 1137 29b2 abf7 3af7 51fe 3cf4

確かに、これは知的課題ではなく、ダクトテーププログラミングに似ています


-6
new Regex(Guid.NewGuid().ToString())

英数字と ' -'(いずれも正規表現の特殊文字はありません)のみを含むパターンを作成しますが、同じ文字列が以前のどこかに出現することは統計的に不可能です(それがGUIDの要点であるためです)。


2
「統計的に不可能」?え?GUIDの計算方法に応じて、次のGUIDを予測することは可能であり、多くの場合非常に簡単です(それらはGUIDを計算するマシンと時間に依存するため)。「ありそうもない」、「確率が非常に低い」という意味ですが、完全にランダムな文字列であっても「不可能」とは言えません。あなたの正規表現は無制限の数の文字列に一致します-この質問は何にも一致しないものを探しています。ずっと。
Ferdinand Beyer 2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.