なぜ正規表現は病的なほど魅力的ですか?


23

図表1図表2、他の例を思い出すのは難しくないと思います。

問題は、問題を解決する方法が複数ある場合、PHPプログラマー(私は通常StackOverflowでPHPタグを参照します)が正規表現に関連するソリューションのヘルプを求めます。

場合でも、それは、あまり経済的になる場合でも、 PHPのマニュアルは(示唆リンクを使用するために)str_replaceどんなのではなく、preg_*またはereg_*全く空想の置換規則が必要とされていない場合機能。

誰かがこれがなぜ起こるのかについての手がかりを持っていますか?

誤解しないでください。私の親友の何人かは正規表現であり、Perlを軽deしていません。私が手に入らないのは、オーバーキルが明らかな場合(文字列を切り替える正規表現)またはコードの複雑さが指数関数的に増加する場合(PHPで htmlからデータを取得するための正規表現)


2
PHPマニュアルの実際の内容を引用したい場合があります。
ChrisF

1
彼らは謎めいているので、あなたは排他的なkewl kidz 'クラブの一部になりたいですか?そして主な理由は、マッチまたは抽出を表現する短い方法を提供するためです。ダミーのケース、カスタムパースの方が良いのは確かですが、開発者は簡単な正規表現を書くよりも正規表現を優先します。
ヘイレム

あなたはその最後の文の間違った部分を強調しました:それのとんでもない部分は「PHPで」ではなく「htmlから」です。
イズカタ

回答:


20

なぜ正規表現は病的なほど魅力的ですか?

潜在意識レベルでは、彼らは包括的で自己調整しながら(パターンを考えて)、それ自体で多くのことを達成できるスマートなプログラム全体のように感じるからです。

これが、人々がすぐに正規表現がテキストベースのタスクのいずれかを解決すると信じる理由であり、どういうわけか、それがやりすぎかもしれないと考えず、それを理解できないかもしれません(言語を解析する)。

魔法の力を含む小さなもの。あなたはノーと言うことはできません、あなたはできますか?


5
+1-小さな謎めいたもの。
AJジョンソン

ホビットはだまされやすい
ベン・デモット

49

持っている唯一のツールが正規表現である場合、すべての問題は次のようになります ^((?>[a-zA-Z\d!#$%&'*+\-/=?^_{|}~]+\x20*|"((?=[\x01-\x7f])[^"\\]|\\[\x01-\x7f])*"\x20*)*(?<angle><))?((?!\.)(?>\.?[a-zA-Z\d!#$%&'*+\-/=?^_{|}~]+)+|"((?=[\x01-\x7f])[^"\\]|\\[\x01-\x7f])*")@(((?!-)[a-zA-Z\d\-]+(?<!-)\.)+[a-zA-Z]{2,}|\[(((?(?<!\[)\.)(25[0-5]|2[0-4]\d|[01]?\d?\d)){4}|[a-zA-Z\d\-]*[a-zA-Z\d]:((?=[\x01-\x7f])[^\\\[\]]|\\[\x01-\x7f])+)\])(?(angle)>)$


16
この答えを選んだ誘惑は非常に強いですが、ここで開かれた最初の質問なので、私は抵抗しなければならないと思います。
cbrandolino

1
@Dev、それは十分に理にかなっています。私のコメントは、答えに対する感謝を表すための、おそらく面白い方法でした。
cbrandolino

17
これは一体何ですか?
トム・オコナー

4
私は知らない...これは全体をかなりまとめていると思う。正規表現を知っていて、他の方法がわからない場合、なぜ探しに行きますか?あなたはすでに、正しく行われれば仕事を処理するツールを持っています。単純なメソッドに出くわすか、それについて知らされるまで、必要以上に複雑であっても、正規表現は包括的なメソッドになります。
Aeo

4
@Tom O'Connor RFC 2822の電子メールアドレスを照合するのは正規表現に近いと思いますが、マークダウンで大混乱を引き起こしているため、2、3文字を削除する必要がありました。
グレナトロン

23

私はそれが理由だと思う:

  1. 同等のコードと比較して(適切に使用した場合)素晴らしく簡潔であり、
  2. これらはプログラミング言語全体で広くサポートされているため、ほとんどの開発者はそれらに精通しています。

3
#2は理にかなっています。
cbrandolino

23

私のキャリアの初期段階(すなわち、PHP以前)で、私はPerlの第一人者であり、Perlの第一人者の主要な側面の1つは正規表現の習得です。

現在のチームでは、文字通り、他の(通常は厄介な)ツールの前に正規表現に手を伸ばすのは私たちだけです。他のチームにとっては、彼らは純粋な魔法のようです。彼らは私の机に回り、正規表現を要求します。正規表現は、文字通り10秒で組み立てられ、それが機能すると吹き飛ばされます。私は知らない-私は彼らと長い間働いてきた、それはちょうどこの時点で自然です。

正規表現の流encyさがないと、strstrステートメントとstrposステートメントをラップするフロー制御ステートメントの組み合わせが残ります。私は、30行のlo索する文字列検索よりも、1つのエレガントな正規表現を作成したいです。


2
これを十分に支持することはできません。
CaffGeek

8
私は興味があります:正規表現を書くのと同じくらい流readに読んでいますか?
ピーターヘン

7
正規表現のトレーニングセッションを定期的に開催していることや、コードから地獄を記録していることを願っています。それ以外の場合は、同僚のサポートの悪夢を作成しています。「エレガントな正規表現」が何をしているかを理解しようとする人々によって、正規表現が100倍以上失われる可能性があると書いて節約した時間。
ジェフネクト

3
とても素晴らしい。これらのコメントで、正規表現の愛と憎しみの綱引きを聞くことができます。
ダン・レイ

1
@Ben Lee:そうですね-OTOH、コメントされた正規表現に出会ったことはありません。正規表現の問題のいくつかは、冷静さの態度に基づいている可能性があります。
ピーターチェン

16

それどころか。人々は正規表現を邪悪なミームのように頻繁にIMOしている。preg_matchがで過度に使用されphpていることは明らかですが、(PHPで)そうするのが賢明であることが多いことはそれほど明白ではありません。

私はこれまでのところ、文字列関数を使用することはPHPランドのさらに別のマイクロ最適化であると推測します。多くの有用なものがあり、通常はより良い選択です。しかし、あなたは避けるべきではありませんpreg_match複数の賛成でstrposかつifチェーン。実際には判明しているため、libpcreは多くの場合、PHPが文字列の代替を探すループを実行するよりも高速です。

最近の例で気づいたように、文字列がすべて小文字であるかどうかをテストします。

 if ($string == strtolower($string))

より読みやすい:

 if (!preg_match("/[A-Z]/", $string))

そして、あなたは、それがすべてPHPであるので、最初のものがより速くなければならないと仮定するでしょう。しかし実際には、正規表現は文字列を1回だけ参照し、大文字が見つかるとすぐに否定条件を中止できます。ただし、strtolower()アプローチは文字列を2回調べます。最初のstrtolower()は、各文字を繰り返し、比較して大文字にすることにより、文字列を複製します。次に、==オリジナルとコピーを繰り返し、もう一度それらを比較します。

したがって、それは明らかなケースではありません。また、客観的になるために、通常は短い文字列を比較するだけなので、最初の方が速いことがよくあります。しかし、PHPの文字列関数は常に正規表現よりも賢明であるという仮定に盲目的に進まないことが不可欠です。

(xhtml- regexesに関する@bobinceの楽しい答えと、それが最近非常に役に立たない方法でリンクされることが多い方法について、別の不満を追加したいと思います。そして、以下のより客観的な答えは無視されます。)


1
あなたの例に同意します。それでも、この特定のケースでは、とにかく「strtolower()」を好むでしょう:重要ではないコードでは、このような大きな(他の実装に比べて)実行時間の最適化は重要ではありません-小文字を評価したい場合を除きます-巨大なテキストファイルのように見えますが、それが役立つケースは想像できません。
cbrandolino

1
@cbrandolino:議論はありません。このようなものは、ネストされたループに関連性があり、評価されるだけで、事実上の違いが生じる可能性があります。
マリオ

4
+1事実、人々は常にサポートされているよりもはるかに多くそれらを打ちます。
オーブリング

1
「regexp bashers」の1つとして:ワンライナーが多かれ少なかれ、30行を解析する「手動」文字列を表すのを見るのは楽しいです。ただし、最も現実的な例では、メンテナンスに苦労します。さらに、それらを未検証の入力に適用しようとすると、拒否された入力に適した診断を生成するには追加のアクロバットが必要です。私にとっては、これは典型的な「書き込み専用」コードです-迅速なスクリプト、長生きするアプリには不向きです。
ペテルヘン

1
すべての正規表現を/xモードで書いていない人は、認識チャンクのエルボルームに空白を許可し、物事が行われている理由を説明するコメントは、もちろん彼の耳を囲んでおくべきです。しかし、合理的な複雑さの実際の正規表現については、文法正規表現を介したトップダウン設計の適用を検討する必要があります。一度光を見たら、二度と戻ることはありません/@#$^^@#$^&&*)@#/
-tchrist

8

正規表現は、正規言語を解析するための最適なツールであるため、非常に魅力的です。

次の利点があります。

  • 彼らは簡潔です。通常、正規表現を使用するよりも、特定のアルゴリズムを使用して特定の通常の言語を解析するには、より多くのコードが必要です。
  • 彼らは素早く使用します。通常、正規表現を使用するよりも、特定のアルゴリズムを使用して特定の通常の言語のパーサーを作成するのに多くの時間がかかります。
  • 彼らは簡単です。一連の特殊文字とその意味を学習すると、正規表現を簡単に作成できます(ただし、それらを読むのは少し難しくなります)。正規表現は言語そのものです-私たちの種は言語が非常に上手になるように進化したため、有用な特性です。
  • 彼らは速いです。コンパイルすると、NO(N)時間で文字列の長さと一致します。
  • 彼らは柔軟です。それらは通常の言語に一致し、多くのデータは通常の言語として表現されます。
  • 彼らは遍在しています。ほとんどのプログラミング言語には、外部ライブラリを介するか、言語自体に埋め込まれた基本的な正規表現がサポートされています。正規表現言語自体の違いもあまりありません。

これにより、彼らは彼らが適している状況に魅力的になりますが、人々は彼らが最良のツールではない状況でそれらを使用するかもしれません。

  • 一致するものが正規表現(HTMLなど)を使用して表現できないことを理解しないでください。
  • 怠け者(悪い方法で)-彼らはツールを知っており、それが彼らがしていることにとって最良のツールではないことを認識していますが、95%の時間で問題なく動作し、特定の学習の95%の努力を必要としますパーサーまたはゼロからの書き込み。
  • 彼らはより良いツールが存在することを知りません。

えー、私はいくつかの特定のケースについて言及していました。これらのケースは明らかに最善の方法ではなく、まだ使用されています。私は正規表現が好きです(つまり、退屈で活気がないと思いますが、いくつかのコンテキストでは依然として非常に便利です)、そしてそれらの利点が何であるかを知っています。
cbrandolino

私は残りに同意しますが、迅速で簡単ですか?学習曲線は急です:初心者にとって、式が機能しない理由を理解することは困難であり、すべての正規表現の実装には少なくとも微妙な違いがあるようです。
ペテルヘン

なぜすべての人が、本格的なWebページを完全な解析ツリーに完全に解析することで、HTMLの小さな部分を引き出すのと混同するのですか?それは本当に愚かです。私を信じてください、私がHTMLページを編集するときvi、あなたは私:%s/foo/bar/gcがそれで使うあなたの人生を賭けます。エディターとして十分であれば、スクリプトとしても十分です。
-tchrist

6

うーん、私は推測することができます。コードの30行が20文字の正規表現に置き換えられたことを経験した人もいるかもしれません。そのため、正規表現を使用できる場合、代わりに他のものを使用するのは間違っていると感じます。


4

それは一部の人々がどのように考えるかに適合します。私はそれらが好きではありませんが、正規表現で考えるように見える友人がいます。彼らの脳のパターンマッチングの部分は、正式な論理のものよりも露出していると思います。:-)


6
理にかなっている進化の歴史に関して。文法を定義したり、三段論法を発見するずっと前に、パターンを照合していました。
グレナトロン

1
私は同意しません、プログラミングにはロジックとパターンマッチング、2つの領域が含まれます。正規表現はパターンマッチングに非常に優れているため、このようなタスクに使用する必要があります。「私は彼らが好きではない」と言っても、特定の仕事に適したツールを捨てることです。
オーブリング

@Orbling:問題は、彼らが良いか悪いかということではありませんが、なぜ一部の人々はそれらを使いすぎ、他の人はそうしないのか。
レナートレゲブロ

質問かもしれませんが、あなたの答えは、両方ではなく、どちらか一方の心が働いていることを示唆しています。
オーブリング

「提案」は正しい言葉だとは思いません。
レナートレゲブロ

3

正規表現の遍在性は、文​​字列の遍在性によるものだと思います。文字列は最も単純なデータ構造であり、ほとんどの人が最初に学習します。コードはすべてシンボリック形式で記述されているため、プログラマーがシンボリック形式で何かをモデリングすることを検討するのは自然なことです。しかし、新しいシンボリックフォームの構文を拡張しようとするときにプログラミング言語に抵抗がある場合、それらはすべて引用符で囲まれています。リレーショナルデータモデルにはSQLがあります。XMLデータモデルにはXQueryがあります。しかし、謙虚な文字列データモデルについてはどうでしょうか。正規表現!

昨日、HTML5ゲーム開発をサポートする光沢のある新しいJavascriptフレームワークのAPIを探していました。ゲームに必要なメインサブシステムを記述するための宣言メカニズムがあります。これらの機能をどのように指定しますか?JSON?流dotなドット表記?アレイ?いいえ-コンマと空白で区切られた機能名のリストを含む文字列。そのリストをどのように解析するのだろうか...?


2

一度に全部を見ることができるからです。全体を見ることができることで、作業が簡単になります。それは常に素晴らしいことです。それは、多くのC ++プログラマーがまだprintf-typeステートメントを使用している理由のようなものです:それはタイプセーフではありません(少なくともgccはprintfステートメントのタイプをチェックできます)。

それが十分に単純な正規表現である場合、それらは多くの場合、物事を行うための最良の方法です-コンパクトなフォームと多くの機能により、特定のタスクに最適です。問題は、正規表現をそれ以上読めないほど複雑にする場合、または単純な文字列操作でより迅速に実行できることを行うために複雑な正規表現を使用する場合に発生します。

正規表現は、他の強力なツールと同様に、適切な節度で使用する必要があります-多すぎず、少なすぎません。また、パフォーマンスが大きな懸念事項でない限り、単一の正規表現は、一連の文字列操作よりも記述が速く、デバッグが容易な場合があります。


2

うーん、現在の答えは、技術的な側面にあまりセンター、(可読性の長所/短所である重要なポイント)。それでは、PHP環境/コミュニティにもう少しシフトさせてみましょう。

  • PHPはPerlの小さな義姉妹です。そして、Perlの不可欠な部分は正規表現です(彼らはそのようなものを発明しましたよね?)。したがって、PHPでも正規表現が普及している理由の1つです。
  • ユースケース PHPの正規表現のためのユースケースとは異なり、偶然あまりないです。PHPは、HTMLページを接着するために構造的に使用されます。そして、正規表現はテキストに対して機能します。(WReachが言ったこと)
  • マイクロ最適化。前に述べたように、人々は知覚速度の後、正規表現やPHP文字列関数を頻繁に使用します。PHPサークルの中心的な問題で、正規表現に固有のものではありません。
  • 正規表現は組み込みです。Pythonで、Javaで、C#で、Rubyで?可用性はありますが、追加のモジュールをロードする必要があるという抑止力があります。そして、それがコア機能であるPHPまたはJavascriptで、使用パターンがどのように異なるかを見てください。別の展示:より頻繁に使用されるCSS。
  • PHPマニュアルは、障害があります。それはしばしばです。正規表現は、容易に発見され、そしてそれはその自明で退屈だので、私はこの楽しい事実を延期:すべてのいまいましいチュートリアルとPHPの導入ブックは常に正規表現について教えるが、教育するために失敗するユースケースに。
  • PHP の文字列APIは、魔法の引用符と名前空間\区切り記号をもたらした同じ人々によって設計されました。Javaよりも包括的ですが、全体的に魅力的ではありません。特に、文字列がオブジェクトを兼ねる場合(Pythonを参照)、文字列関数が正規表現を上回る可能性があります。

しかし、それはちょうどサイドノートとして。とにかく、一般的に正規表現を使いすぎたり、見落としたりする原因となるのは、主に知覚的および技術的な理由だと思います。しかし、PHPとそのユーザーベースには、それを複雑にするいくつかの特性があり、なぜそれについてSOでより多くの質問が表示されるのか(引用が必要です!)、それらはそこで「病的に魅力的」です。


1

私は一般的に正規表現が好きで、それらを置き換える必要がある20行のコードよりも読みやすく、理解しやすいと思います。短い正規表現はすぐに読み取られて理解され、比較的簡単に維持できます(式を変更する場合、変更するコードは20行ありますが、変更するのは1行のみです)。それらが誤用される場合もありますが、他の多くのものも同様です。

おそらくこれらの悪用が多すぎるのは、StackOverFlowのPHPセクションを閲覧しているのは、多くの未熟なPHPプログラマーがいることに気付いているからです。


1

なぜ正規表現は病的なほど魅力的ですか?

そうではありません。彼らは実際には地獄のようにいです。そして理解できない。彼らは憎むべきものであり、できるだけ早く殺されるべきです。

さて、これを言って、私は小さなPerlアプリのデバッグに戻ります。それを助けることはできません。残念ながら、彼らはまだ仕事に最適なツールです。


4
私は正規表現が「正規」でも「表現的」でもないことを言うのが好きです
アンドリューバーバー

2
あなたはそれらを理解していない場合、彼らはくて理解できない。正規表現の禅を達成すると、それらは本当に非常にエレガントです。
ダン・レイ

1
-1すべてのプログラマーがあいまいになることを好むと判断し、他の考えられる説明を考慮しない。...それらがい、または理解できないと思う理由を述べることは助けになるでしょう。
マクニール

1
@Macneil-お願いします(そうですが、私の考えはその線に沿っています)。あなたの質問に関する限り、あなたはそれらを美しいと思いますか?!...しません。そして、これは主観的なサイトであり、それは主観的な意見であるため、私はそれについて詳しく述べる必要も、望んでもいません。そのことに関しては、私も試みません。
ルーク

1
@Rook-ほとんどの人は複雑な正規表現を見て、すべての正規表現が見苦しいと判断し、考えをやめると思います。事実、それらについての偏見を打ち消すことができれば、それらは非常にエレガントで表現力豊かなツールです。ところで、あなた自身のロジックでは、多くのプログラマーが代数をすることはできません。したがって、代数はおそらく本質的に悪であり、明らかにあまり理解できないので廃止すべきです。
ダン・レイ

0

人間は道具を使う生き物であり、正規表現は強力な道具です。正規表現のいい例えは、デリの肉スライサーです。紙のように薄い七面鳥のスライス、コンビーフなどが必要な場合は、それだけです。しかし、それを使うには熟練した手が必要です。なぜなら、あなたはそれで本当にひどく自分自身を切ることができ、血を見るまで物を感じないからです。これが意味することは、正規表現の大きな問題は、正規表現をわずかに無効にすることであり、一致するべきではないものに一致することです。


0

正規表現は力を振るうため、非常に魅力的です。ごく少数のキャラクターで非常に複雑な作業を行うことができます。

問題は、標準的な正規表現の構文がされていることであるないチューリング完全にあなたは、単に正規表現を実装することができない、と人々がいないプログラムがあることを意味している知っている彼らは、正規表現の皮相電力によって魅了されたときということに。

これは-私が推測する-「今、彼らは2つの問題を抱えている」というjwz引用の理由です。

Perlの正規表現はチューリング完全であると思いますが、明らかに決定的に証明または反証されていないようです。


0

それは有限状態マシンをプログラムする効率的な方法だからです。それは適用するときの強力なツールです。基本的には、FSMをプログラミングするための独自の言語です。これは、言語を知っている場合に役立ち、知らない場合は迷惑です。


0

私の経験では、正規表現は古代の芸術のようなものであり、不明瞭なものもあります。関係する魔術を理解できず、おそらく誰もあなたに説明しないので、一部の人々はそれらにthemします。私は、大学が電子メールを照合するよりもささいなことを教えると聞いたことはありません。それから神秘的な内部の仕組みがあります。ほとんどの人はそれらを理解していないので彼らは遅いに違いありません。そして、最初の試行でそれらを正常に機能させることは、新規参入者にとって常に課題です。

同じことは、Perl、awk、Linux、および光沢のあるボタンや素敵な色の構文を持たないすべてのものについて言えます。ですから、「些細なタスク」に複雑さを加えたようなもので、ループ、分割、スイッチ、魔法を投げるだけで、それでうまくいくかもしれません。しかし、道路の反対側にいる場合、正規表現は美しいクッキーカッターであり、厄介なループやデバッグするものがなくても、シグナルノイズのように見えます。彼らが提供する柔軟性の点でも気に入っています。一致するパターンが変更された場合、アルゴリズムやツール/何でもではなく、正規表現を変更するだけで、うまく機能します。そして、それらは魔法の文字列であるため、必要に応じてソースコードの外に置くことができます。また、perlについて考えさせられるもう1つのことは、20文字以上の正規表現を書いた場合、多くのことを達成したと感じることです。少なくとも私にとっては、とてもきれいでコンパクトです。私は怠け者のプログラマーでもあります。素敵な識別とコメントを使って多くのコードを書いて、ミックスにバグを追加するのは好きではありません。

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