web-dev-qa-db-ja.com

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

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

ことは、問題を解決する方法が複数ある場合、PHPプログラマー(私は通常、StackOverflowでPHPタグを閲覧します)が助けを求めます)正規表現を含むソリューションについて。

いつでもそれは経済的ではありません、いつでもPHPマニュアルが示唆します( link )を使用するにはstr_replaceの代わりにpreg_*またはereg_*ファンシー置換ルールが不要な場合の関数。

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

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

23
cbrandolino

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

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

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

魔法の力を含む小さなもの。ノーと言えませんね

20
user8685

あなたが持っている唯一のツールが正規表現である場合、すべての問題は^((?>[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)>)$のようになります

49
glenatron

私はそれが理由だと思います:

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

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

私の現在のチームでは、他の(通常はより厄介な)ツールよりも前に正規表現に到達するのは文字通り私一人だけです。チームの他のメンバーにとっては、それらは純粋な魔法のようです。彼らは私の机に行き、文字通り10秒でまとめられる正規表現を要求し、それが機能するときに吹き飛ばされます。わからない-私は長い間彼らと仕事をしてきたので、現時点では自然なことだ。

Regex-fluencyがないと、strstrとstrposステートメントをラップするフロー制御ステートメントの組み合わせが残り、醜く頭の中で実行するのが難しくなります。私は、30行の文字列検索のプロトタイプよりも、エレガントな正規表現を1つ作成したほうがいいです。

23
Dan Ray

それどころか。人々は、正規表現が悪であるミームをあまりにも頻繁に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の楽しい答え について別の暴言を加えたいと思っています。そして、それが最近非常に役に立たない方法でリンクされている方法です。そして、以下のより客観的な答えは無視されます。)

16
mario

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

それらには次の利点があります。

  • それらは簡潔です。一般に、正規表現よりも、特定のアルゴリズムを使用して特定の正規言語を解析するために必要なコードが多くなります。
  • quickを使用します。一般に、正規表現を使用するよりも、特定のアルゴリズムを使用して特定の正規言語用のパーサーを作成する方がはるかに時間がかかります。
  • 簡単です。特殊文字のセットとその意味を学習したら、正規表現を作成するのは簡単です(ただし、少し読みにくい)。正規表現はそれ自体が言語です。私たちの種は言語が非常に上手に進化したため、有用な特性です。
  • それらはfastです。コンパイルすると、文字列の長さNをO(N)時間で照合できます。
  • それらは柔軟です。それらは任意の通常の言語と一致することができ、私たちのデータの多くは通常の言語として表現されます。
  • それらはユビキタスです。ほとんどのプログラミング言語は、外部ライブラリを介して、または言語自体に組み込まれた、基本的な正規表現をサポートしています。また、正規表現言語自体の間にあまり大きな違いはありません。

これにより、それらが適している状況では魅力的になりますが、次の理由により、最適なツールではない状況で使用される場合があります。

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

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

6
user281377

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

4
Lennart Regebro

正規表現の普及は文字列の普及に起因すると思います。文字列は最も単純なデータ構造であり、ほとんどの人が最初に学ぶものです。すべてのコードはシンボリック形式で記述されているため、プログラマが何かをシンボリック形式でモデル化することを検討するのは自然です。しかし、私たちのプログラミング言語がその構文を私たちの賢い新しいシンボリック形式に拡張しようとするときに抵抗を提供する場合、それらはすべて引用符の間に終わります。リレーショナルデータモデルにはSQLがあります。 XMLデータモデルにはXQueryがあります。しかし、控えめな文字列データモデルについてはどうでしょうか。正規表現!

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

3
WReach

うーん、現在の答えは技術的な側面と読みやすさの長所と短所に重点を置いています(これはです重要なポイントです)。それでは、もう少しPHP environment/community:

  • PHPはPerlですstepsister。そして、Perlの不可欠な部分は正規表現です(正規表現が発明されたのではないでしょうか)。したがって、PHPでも正規表現が普及している理由の1つです。
  • 使用例 PHPは、偶然にも正規表現の使用例と大差ありません。PHPは、構造的にHTMLを接着するために使用されますページと正規表現はテキストで機能します(WReachの発言)
  • マイクロ最適化。前に述べたように:人々は正規表現やPHP文字列関数を使用した後、文字列関数を頻繁に使用します。PHPサークルのコア問題、正規表現に固有ではありません。
  • 正規表現は組み込みです。 Python、Java、C#、Ruby?可用性はありますが、追加のモジュールをロードする必要がありません。そしてPHPまたはそれがコア機能であるJavascriptで、使用パターンがどのように異なるかを見てください。別の展示:それがより頻繁に使用されているCSS。
  • PHPマニュアルに問題があります。それはしばしばです。正規表現は簡単に見つけることができますが、明白なことに退屈なので、この楽しい事実を延期しました。いまいましいチュートリアルとPHP導入本は常に正規表現について教えていますが、ユースケース。
  • string API in PHPは、魔法の引用符と名前空間\セパレーターをもたらしたのと同じ人々によって設計されました。これは、Javaより優れていますが、魅力的ではありません。特に、文字列がオブジェクトとしても機能する場合(Pythonを参照)、文字列関数が正規表現をしのぐ可能性があります。

しかし、それは副次的な注意事項です。とにかく、正規表現の使いすぎや回避につながるのは、主に知覚的および技術的な理由だと思います。まだPHPとそのユーザーベースには、それを合成するいくつかのプロパティがあり、なぜSOについてそれ以上の質問が必要なのか[引用が必要です!]病的に魅力的」があります。

2
mario

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

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

正規表現は、他の強力なツールと同様に、適切なモデレーションで使用する必要があります。多すぎず、少なすぎません。また、パフォーマンスが大きな問題でない限り、単一の正規表現は、一連の文字列操作よりも、書き込みが速く、デバッグが簡単な場合があります。

2
Michael Kohne

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

あなたがそれらの多くの乱用を見ているのは、StackOverFlowのPHPセクションをブラウジングしているからです。なぜなら、そこには未熟なPHPプログラマーがたくさんいることを知っているからです。

1
stoj

なぜ正規表現が病的なほど魅力的であるのですか?

そうではありません。彼らは地獄のように醜いです。そして不可解。彼らはできるだけ早く殺されるべき嫌悪者です。

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

1
Rook

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

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

0
alfa64

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

問題は、標準の正規表現構成がnot Turing-completeであることです。つまり、正規表現では実装できないプログラムがあり、人々はそうではありません[〜#〜] know [〜#〜]正規表現の見かけのパワーに魅了されたとき。

これが、私が推測しているように、「今では2問題がある」というjwz-quoteの理由です。

私は推測 Perlの正規表現はチューリング完全であると思いますが、どうやらそれはまだ決定的に証明または反証されていません。

0
user1249

人間は道具を使う生き物であり、正規表現は強力な道具です。正規表現のいいメタファーは、デリのミートスライサーです。七面鳥やコンビーフなどの薄手のスライスが必要な場合は、それだけです。しかし、それを使うには熟練した手が必要です。あなたはそれで本当にひどく切れる可能性があり、血を見るまで物事を感じないからです。つまり、正規表現の大きな問題は、正規表現がわずかに外れることです。つまり、一致してはいけないもの、またはその逆に一致することを意味し、プロセスの途中で問題が発生するまで、そのことはわかりません。

0
Larry Coleman

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

0
DanTilkin