なぜ正規表現は物議を醸すのですか?[閉まっている]


212

正規表現(別名RegEx-es)を探索するとき、正規表現を聖杯と見なしているように見える多くの個人がいます。とても複雑に見える何か-どんな質問への答えでなければなりません。彼らはすべての問題が正規表現を使用して解決できると考える傾向があります。

一方、正規表現を絶対に避けようとする人も多い。彼らは、正規表現がよりコンパクトなソリューションであるとしても、正規表現を回避する方法を見つけ、そのためだけに追加のコーディングを受け入れようとします。

なぜ正規表現が物議を醸すと考えられているのですか?それらがどのように機能するかについての広範な誤解はありますか?それとも、正規表現は一般的に遅いと広く信じられているのでしょうか?


9
これがディスカッションの場合は、閉じないでください。しかし、私はそこに本当の質問を見つけたので、おそらくディスカッションタグは属していませんか?
RCIX 2009年

6
冗談ではありません。あなたはそれを持ち出して、人々はここですべて狂っています。
ライアンフローレンス

1
質問の見事な表現と言い回し!
imz-Ivan Zakharyaschev 2011年


質問は意見に基づいており、ルールもここに適用する必要があります(または、質問を編集して正確な回答を対象にする必要があります)。それは私が正規表現の論争がそれについてのチュートリアルとマニュアルの不正確さから来ていると思いますと言った。ほとんどの場合、すべての時間情報が混在しているわけではなく、さらにすべての特性が与えられているわけではありません。その言葉の使い方のミスに加えて、あなたは最終的に何かを学び、それが何か他のものを意味するかもしれないことに気づくでしょう。そして最後に、特別な正規表現文字は、混乱を増やす1つの意味に限定されません。
intika

回答:


136

遅いので正規表現に反対する人はいないと思います。むしろ、読み書きが難しく、正しく理解するのが難しいためです。正規表現が問題に対して効果的でコンパクトな解決策を提供する状況もありますが、読みやすく保守しやすいコードのセクションを使用する方がよい状況に追い込まれる場合があります。


2
そして、はい、正規表現は、単純な関数を使用する場合に比べて非常に遅くなる可能性があります。また、低速であるだけでなく、任意の(ユーザー指定の)入力に直面した場合、正規表現エンジンのパフォーマンスは完全に予測できません
Pacerier、2015

1
正規表現がどのように機能するかを知っている場合は、まったく問題ありません。
Shiplu Mokaddim 2017年

8
@pacerier、それは遅いパターンではなく、遅いエンジンです。ほとんどの(現代の)正規表現エンジンは、スタックマシンとバックトラッキングを使用するため、複雑なパターン(たとえば、多数|または.*)には適していません。そのため、Perl、Java、Python、Rubyなどで正規表現を慎重に調整する必要がありますgrep。まず、古いスタイルの正規表現エンジン(たとえば)を使用して、パターンをDFAにコンパイルします。その後、パターンの複雑さはほとんど関係ありません。同じテキストとパターンに22分と2秒のJavaとgrepを使用しました。これが科学です:swtch.com/~rsc/regexp/regexp1.html
hagello

122

正規表現を保守可能にする

以前「正規表現」と呼ばれていたパターンをわかりやすくするための大きな進歩は、Perlの/xregexフラグ(?x)(埋め込み時に書き込まれることもあります)で、空白(改行、インデント)とコメントを許可します。これにより、可読性が大幅に向上し、保守性が向上します。空白は認識チャンクを可能にするので、どのグループのどのグループかを確認できます。

現代のパターンは現在、比較的番号付きと名前付きの両方の後方参照もサポートしています。手段あなたが必要であることを把握するためにキャプチャグループをカウントする必要のないこと$4\7。これは、他のパターンに含めることができるパターンを作成するときに役立ちます。

これは、比較的番号が付けられたキャプチャグループの例です。

$ dupword = qr {\ b(?:(\ w +)(?:\ s + \ g {-1})+)\ b} xi;
$ quoted = qr {(["'])$ dupword \ 1} x;

次に、名前付きキャプチャの優れたアプローチの例を示します。

$dupword = qr{ \b (?: (?<word> \w+ ) (?: \s+ \k<word> )+ ) \b }xi;
$quoted  = qr{ (?<quote> ["'] ) $dupword  \g{quote} }x;

文法正規表現

何よりも、これらの名前付きキャプチャは(?(DEFINE)...)ブロック内に配置できるため、パターンの個々の名前付き要素の実行から宣言を分離できます。これにより、パターン内のサブルーチンのように動作します。
この種の「文法上の正規表現」の良い例は、この回答これにあります。これらは文法宣言のように見えます。

後者があなたに思い出させるように:

…ラインノイズのパターンは絶対に書かないでください。必要はありませんし、すべきではありません。空白、コメント、サブルーチン、または英数字の識別子を禁止するプログラミング言語は維持できません。したがって、パターンではこれらすべてのものを使用してください。

これは強調しすぎることはできません。もちろん、それらをパターンで使用しないと、悪夢が生じることがよくあります。あなたがいる場合でも行うものの、それらを使用し、あなたがする必要はありません。

RFC 5322を解析するための、現代の文法パターンの別の例を次に示します。

$rfc5322 = qr{

   (?(DEFINE)

     (?<address>         (?&mailbox) | (?&group))
     (?<mailbox>         (?&name_addr) | (?&addr_spec))
     (?<name_addr>       (?&display_name)? (?&angle_addr))
     (?<angle_addr>      (?&CFWS)? < (?&addr_spec) > (?&CFWS)?)
     (?<group>           (?&display_name) : (?:(?&mailbox_list) | (?&CFWS))? ; (?&CFWS)?)
     (?<display_name>    (?&phrase))
     (?<mailbox_list>    (?&mailbox) (?: , (?&mailbox))*)

     (?<addr_spec>       (?&local_part) \@ (?&domain))
     (?<local_part>      (?&dot_atom) | (?&quoted_string))
     (?<domain>          (?&dot_atom) | (?&domain_literal))
     (?<domain_literal>  (?&CFWS)? \[ (?: (?&FWS)? (?&dcontent))* (?&FWS)?
                                   \] (?&CFWS)?)
     (?<dcontent>        (?&dtext) | (?&quoted_pair))
     (?<dtext>           (?&NO_WS_CTL) | [\x21-\x5a\x5e-\x7e])

     (?<atext>           (?&ALPHA) | (?&DIGIT) | [!#\$%&'*+-/=?^_`{|}~])
     (?<atom>            (?&CFWS)? (?&atext)+ (?&CFWS)?)
     (?<dot_atom>        (?&CFWS)? (?&dot_atom_text) (?&CFWS)?)
     (?<dot_atom_text>   (?&atext)+ (?: \. (?&atext)+)*)

     (?<text>            [\x01-\x09\x0b\x0c\x0e-\x7f])
     (?<quoted_pair>     \\ (?&text))

     (?<qtext>           (?&NO_WS_CTL) | [\x21\x23-\x5b\x5d-\x7e])
     (?<qcontent>        (?&qtext) | (?&quoted_pair))
     (?<quoted_string>   (?&CFWS)? (?&DQUOTE) (?:(?&FWS)? (?&qcontent))*
                          (?&FWS)? (?&DQUOTE) (?&CFWS)?)

     (?<word>            (?&atom) | (?&quoted_string))
     (?<phrase>          (?&word)+)

     # Folding white space
     (?<FWS>             (?: (?&WSP)* (?&CRLF))? (?&WSP)+)
     (?<ctext>           (?&NO_WS_CTL) | [\x21-\x27\x2a-\x5b\x5d-\x7e])
     (?<ccontent>        (?&ctext) | (?&quoted_pair) | (?&comment))
     (?<comment>         \( (?: (?&FWS)? (?&ccontent))* (?&FWS)? \) )
     (?<CFWS>            (?: (?&FWS)? (?&comment))*
                         (?: (?:(?&FWS)? (?&comment)) | (?&FWS)))

     # No whitespace control
     (?<NO_WS_CTL>       [\x01-\x08\x0b\x0c\x0e-\x1f\x7f])

     (?<ALPHA>           [A-Za-z])
     (?<DIGIT>           [0-9])
     (?<CRLF>            \x0d \x0a)
     (?<DQUOTE>          ")
     (?<WSP>             [\x20\x09])
   )

   (?&address)

}x;

それは驚くべきことではありませんか—そして素晴らしいですか?BNFスタイルの文法を取り、その基本的な構造を失うことなくコードに直接変換できます。

それでも現代の文法パターンでは不十分な場合は、Damian Conwayの優れたRegexp::Grammarsモジュールが、より明確な構文と優れたデバッグ機能を提供します。RFC 5322リキャストを解析してそのモジュールからパターンに変換するための同じコードを次に示します。

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;
use Data::Dumper "Dumper";

my $rfc5322 = do {
    use Regexp::Grammars;    # ...the magic is lexically scoped
    qr{

    # Keep the big stick handy, just in case...
    # <debug:on>

    # Match this...
    <address>

    # As defined by these...
    <token: address>         <mailbox> | <group>
    <token: mailbox>         <name_addr> | <addr_spec>
    <token: name_addr>       <display_name>? <angle_addr>
    <token: angle_addr>      <CFWS>? \< <addr_spec> \> <CFWS>?
    <token: group>           <display_name> : (?:<mailbox_list> | <CFWS>)? ; <CFWS>?
    <token: display_name>    <phrase>
    <token: mailbox_list>    <[mailbox]> ** (,)

    <token: addr_spec>       <local_part> \@ <domain>
    <token: local_part>      <dot_atom> | <quoted_string>
    <token: domain>          <dot_atom> | <domain_literal>
    <token: domain_literal>  <CFWS>? \[ (?: <FWS>? <[dcontent]>)* <FWS>?

    <token: dcontent>        <dtext> | <quoted_pair>
    <token: dtext>           <.NO_WS_CTL> | [\x21-\x5a\x5e-\x7e]

    <token: atext>           <.ALPHA> | <.DIGIT> | [!#\$%&'*+-/=?^_`{|}~]
    <token: atom>            <.CFWS>? <.atext>+ <.CFWS>?
    <token: dot_atom>        <.CFWS>? <.dot_atom_text> <.CFWS>?
    <token: dot_atom>        <.CFWS>? <.dot_atom_text> <.CFWS>?
    <token: dot_atom_text>   <.atext>+ (?: \. <.atext>+)*

    <token: text>            [\x01-\x09\x0b\x0c\x0e-\x7f]
    <token: quoted_pair>     \\ <.text>

    <token: qtext>           <.NO_WS_CTL> | [\x21\x23-\x5b\x5d-\x7e]
    <token: qcontent>        <.qtext> | <.quoted_pair>
    <token: quoted_string>   <.CFWS>? <.DQUOTE> (?:<.FWS>? <.qcontent>)*
                             <.FWS>? <.DQUOTE> <.CFWS>?

    <token: word>            <.atom> | <.quoted_string>
    <token: phrase>          <.word>+

    # Folding white space
    <token: FWS>             (?: <.WSP>* <.CRLF>)? <.WSP>+
    <token: ctext>           <.NO_WS_CTL> | [\x21-\x27\x2a-\x5b\x5d-\x7e]
    <token: ccontent>        <.ctext> | <.quoted_pair> | <.comment>
    <token: comment>         \( (?: <.FWS>? <.ccontent>)* <.FWS>? \)
    <token: CFWS>            (?: <.FWS>? <.comment>)*
                             (?: (?:<.FWS>? <.comment>) | <.FWS>)

    # No whitespace control
    <token: NO_WS_CTL>       [\x01-\x08\x0b\x0c\x0e-\x1f\x7f]

    <token: ALPHA>           [A-Za-z]
    <token: DIGIT>           [0-9]
    <token: CRLF>            \x0d \x0a
    <token: DQUOTE>          "
    <token: WSP>             [\x20\x09]

    }x;

};


while (my $input = <>) {
    if ($input =~ $rfc5322) {
        say Dumper \%/;       # ...the parse tree of any successful match
                              # appears in this punctuation variable
    }
}

perlreのマンページ多くの優れた点がありますが、基本的な正規表現の設計機能におけるこれらの劇的な改善は、決してPerlだけに限定されているわけではありません。実際pcrepatternのマンページの方が読みやすく、同じ領域をカバーしています。

現代のパターンは、有限オートマトンクラスで教えられた原始的なものとほとんど共通点がありません。


9
はい!はい!最後に、誰かがx修飾子を使用して読み取り可能な正規表現をどのように読むことができるかを示すすばらしい例を示します。実際にそれを使用することはもちろんのこと、それが存在することを知っている人がどれほど少ないかは信じられません。
Shabbyrobe 2010年

1
@シャビーローブ:それだけではありません/x。正規表現を文法的に使用し、(?&name)内部の正規表現サブルーチンを使用しているため、これは本当に素晴らしいことです。
tchrist 2010年

+1あなたはいつも何か新しいことを学びます。PCREに定義の「偽」条件があることを知りませんでした。
NikiC、2011

5
Pythonにも同様にre.VERBOSEフラグがあります。
メカニカルカタツムリ2013年

3
ただ正規表現を使用できるようにするために人々が行く長さにはまだ驚いていると言ってください。
Slater Victoroff 2015年

68

正規表現は素晴らしいツールですが、人々は「ねえ、なんと素晴らしいツールなのか、Xを実行するためにそれを使用します!」と考えています。ここで、Xは別のツールの方が優れているものです(通常はパーサー)。それは、ドライバーの問題が必要なハンマーを使用する標準です。


4
ほとんどのパーサー(字句解析器)は、正規表現を使用して構文解析を行うことに
注意してください

62
パーサーが正規表現を使用すると言うのは、パーサーが割り当てステートメントを使用すると言うのと同じです。それらがどのように使用されているかを見るまでは、何の意味もありません。
Chas。オーエンス

24
パーサーの方が優れているときにRegExを使用するのは面倒です。言語の標準文字列検索または置換関数が機能するときに(通常は線形時間で)RegExを使用することは許されません。
jmucchiello 2010

1
同意します。RegExはすべての取引のジャックである必要があるため、処理のオーバーヘッドは非常に大きくなります。RegExエンジンの使用が簡単に見えるからといって、反復パーサー(開発者に依存するしきい値)よりも優れたソリューションであるとは限りません。私のお気に入りの例の1つであるPHPのsplit($pattern,$string)vs- explode($delimiter,$string)ありがたいことに、前者の価値は下がっていますが、多くのコードが後者の能力を必要とするだけで前者を使用していました。Aggreed、正規表現のは、いくつかのことを行うための簡単なツールを提供していますが、正規表現、彼らのフルパワー必要がない限り
Rudu

4
字句解析器は実際に正規表現を使用する場合があります。これらはトークナイザーとしても知られていますが、構文アナライザー(またはパーサー)ではありません。十分に複雑な文字列を読み取るには、トークナイザーを使用して文字列をトークンとして読み取る必要があります(おそらく、正規化では、トークン化器によってはそうではありません)。次に、これらのトークンをパーサーに渡す必要があります。パーサーは、これらのトークンを文法規則で処理します。これは、正規表現ではありません。
アクセル

53

正規表現を定期的に使用する(しゃれた目的の)私が知っているほとんどすべての人は、REをgrep、sed、awk、Perlなどのファーストクラスのプログラミング構造として扱うツールを使用するUnix風のバックグラウンドに由来します。正規表現を使用するための構文上のオーバーヘッドはほとんどないため、それらを使用すると生産性が大幅に向上します。

対照的に、REが外部ライブラリである言語を使用するプログラマは、正規表現がテーブルにもたらすことができるものを考慮しない傾向があります。プログラマーの「時間コスト」が非常に高いため、a)REがトレーニングの一部として登場したことがないか、b)REの観点から「考え」ておらず、より身近なパターンに頼ることを好む。


11
ええ、私はライブラリを使用して正規表現構文を冗長にするPythonを決して許しません。正気よりも純粋だと思います。
2010

7
私はUNIXの出身で、sed、awk、およびperlのロードを使用しており、もちろん大量のgreppingを行いましたが、正規表現を使用すると、書き込み専用のハックなので、維持するのが嫌いです。これはシェルスクリプト/ワンタイマーに適していますが、実際の作業では、単にデータを保存するだけではなく、明確な構文で適切なトークナイザー/レクサー/パーサーを使用しています。私のお気に入りはすべて/いずれでも、きれいに+自己最適化できます。私は困難な方法を学びました、そして、長年にわたって、最初の少しの自己規律は後でより少ない努力を意味します。正規表現はキーボード上の瞬間であり、眉をひそめている生涯です。
AndrewC 2012

44

正規表現を使用すると、カスタム有限状態マシン(FSM)をコンパクトな方法で記述して、入力文字列を処理できます。正規表現の使用が難しいのには、少なくとも2つの理由があります。

  • 昔ながらのソフトウェア開発には、多くの計画、紙のモデル、注意深い思考が含まれます。正規表現はこのモデルに非常によく適合します。効果的な表現を適切に記述するには、FSMのパスを視覚化して多くのことを検討する必要があるためです。

    現代のソフトウェア開発者はコードをかなりハンマーで打ち、デバッガーを使用して実行をステップ実行し、コードが正しいかどうかを確認します。正規表現はこの作業スタイルをあまりサポートしていません。正規表現の1つの「実行」は、実質的にアトミック操作です。デバッガーで段階的な実行を観察することは困難です。

  • 意図したよりも多くの入力を誤って受け入れる正規表現を書くのは簡単すぎます。正規表現の値は、実際に有効な入力と一致するものではなく、無効な入力と一致しないものです。正規表現の「ネガティブテスト」を行う手法はあまり高度ではなく、少なくとも広くは使用されていません。

    これは、正規表現が読みづらいところまで行きます。正規表現を見るだけで、拒否されるべきであるが誤って受け入れられる可能性のあるすべての入力を視覚化するには、多くの集中力が必要です。他の誰か正規表現コードをデバッグしようとしたことがありますか?

今日のソフトウェア開発者の間で正規表現を使用することに抵抗がある場合、それは主にこれら2つの要因が原因であると思います。


4
正規表現をデバッグするための優れたツールがあります:regexbuddy.com
Jasper Bekkers

15
perl -Mre = debug -e "q [aabbcc] =〜/ ab * [cd] /"
ブラッドギルバート

15
フライングスパゲッティモンスターのことを考えずに頭字語「FSM」を見ることができるとは思いません。
Shabbyrobe 2010年

4
@Shabbyrobe:私は気分を害するつもりはありません。必要に応じて、確定的有限オートマトン(DFA)を使用できます。
Bill Karwin、2010年

37

正規表現は難しいと考える傾向があります。しかし、それは彼らが間違って使用しているためです。コメント、インデント、名前付きのキャプチャを含まない複雑なワンライナーを記述します。(コメント、インデント、エイリアスを使わずに、複雑なSQL式を1行で詰め込まないでください。)そう、多くの人にとって、彼らは意味をなさない。

あなたの仕事が持っている場合しかし、(...そこに大体どのWebアプリケーション)テキストを解析して行うために、あなたは正規表現を知らない、あなたはあなたの仕事で吸うと、あなたはあなた自身の時間を無駄にしているとのこと、あなた雇用者。あなたが知る必要があるそれらについてのすべてを教えるための優れたリソースがあります。


2
まあ..違いは、他の言語では意味がない正規表現では複数のスペースが意味を持ち、そのため通常は1つのライナー(複数行に折り返される場合がある)です
Rado

14
@Rado:たとえば、Perlには、x空白を無視する正規表現の修飾子があります。これにより、正規表現を数行に配置してコメントを追加できます。
Nathan Fellman

9
同様にPythonにはre.X別名がありre.VERBOSEます。
Craig McQueen

2
同様に、xtcl の修飾子。他の言語とは異なり、tclはPCREを使用しないため、これは非常に標準的だと思います。
slebetman、

2
@AndrewCこれは、この投稿で得られた最も大きな誤解の1つです。
Jasper Bekkers 2013

28

一般的に受け入れられているIDEで最も人気のある学習ツールがないため:Regexウィザードはありません。オートコンプリートすらありません。すべてを自分でコーディングする必要があります。


3
次に、間違ったIDEを使用しています...テキストエディタでさえ、正規表現のヒントを提供しています。
CurtainDog 2009

1
余談ですが、ExpressoとRegex Coachは、正規表現を作成するための非常に便利なツールです。
Mun

22
正規表現をどのようにオートコンプリートしますか?
AmbroseChapel 2009

3
EditPad Proには、検索ボックスに正規表現の構文の強調表示がありますが、役に立たないので不愉快であり、オフのままにします。しかし、対応していない括弧がある場合に知らせてくれて感謝しています。特に括弧は追跡し続けるクマになることができます。
アランムーア

2
@AmbroseChapel-私はこの議論に数年遅れています。しかし、私はregexhero.net/testerでオートコンプリートメカニズムを作成しました。これは、 丸括弧()、角括弧[]、中{}括弧内の一般的な構成要素によって開始されます。また、バックスラッシュで機能します。
スティーブウォーサム


16

彼らがそんなに物議を醸しているとは思わない。

また、あなたは自分の質問にある程度回答したと思います。なぜなら、すべての 場所でそれらを使用する(すべてが通常の言語であるわけではない2)か、まったく使用しないことは愚かなことです。プログラマーであるあなたは、正規表現がコードを助けるとき、またはコードを傷つけるときについて、インテリジェントな決定を行わなければなりません。このような決定に直面したとき、覚えておくべき2つの重要な点は、保守性(読みやすさを意味する)と拡張性です。

特に嫌いな人は、きちんと使うことを学んだことがないのではないでしょうか。きちんとしたチュートリアルでほんの数時間を費やすほとんどの人は、それらを理解し、すぐに流暢になるでしょう。開始する場所についての私の提案は次のとおりです。

http://docs.python.org/howto/regex

このページではPythonのコンテキストでの正規表現について説明していますが、その情報は他の場所にも非常に当てはまることがわかりました。Python固有のものはいくつかありますが、それらは明確に記載されていて、覚えやすいと思います。



@DManありがとう。回答を編集して反映します。
allyourcode 2010

11

正規表現は文字列に対するものであり、算術演算子は数値に対するものであり、議論の余地があるとは思わないでしょう。私のようにかなりひどいOO活動家(ストリングよりも他のオブジェクトを選択する傾向がある)でさえ、拒否するのは難しいと思います。


7

問題は、正規表現が潜在的に非常に強力であるため、正規表現を使用して別の何かを使用する必要があることです。

優れたプログラマは、それらをどこで使用し、どこで使用しないかを知っている必要があります。典型的な例は、非正規言語の解析です(言語が正規かどうかの判断を参照)。

最初は本当の正規表現(拡張なし)に制限すれば、間違いはないと思います。一部の拡張機能はあなたの人生を少し楽にすることができますが、本当の正規表現として表現するのが難しいものを見つけた場合、これは正規表現が適切なツールではないことを示している可能性があります。


5

gotoがなぜ物議を醸すのかについて尋ねるのとほぼ同じです。

基本的に、「明白な」力を手に入れると、人々は彼らが最善の選択肢ではない状況でそれらを乱用する傾向があります。たとえば、正規表現でCSVまたはXMLまたはHTMLを解析することを求める人の数は、驚かされます。それは仕事にとって間違ったツールです。しかし、一部のユーザーはとにかく正規表現の使用を主張します。

個人的に、私はその幸せな媒体を見つけようとします-彼らにとって良いもののために正規表現を使用し、それらが最適ではないときにそれらを避けます。

正規表現は、CSV、XML、HTMLなどの解析に引き続き使用できることに注意してください。ただし、通常、単一の正規表現では使用できません。


もちろん、これらの形式を1つの正規表現で解析できます。これが正規表現の力です。それをしたいかどうかは、まったく別の問題です。
Jasper

4

「物議を醸す」が正しい言葉だとは思わない。

しかし、人々が「そのような文字列操作を行うために必要な正規表現は何か」と言う例をたくさん見ました。これはXY問題です。

言い換えれば、彼らは正規表現が彼らが必要とするものであるという仮定から始まったが、split()、perlのtr ///のような、文字が一方を他方に置き換えられた翻訳、またはただのindex()。


4

これは興味深いテーマです。
多くの正規表現愛好家は、式の簡潔さと効率性を混同しているようです。
その上、多くの考えを必要とする正規表現は、著者にすぐに正当化する大満足を生み出します。

しかし...正規表現は、パフォーマンスが問題ではなく、Perlなどのテキスト出力をすばやく処理する必要がある場合に非常に便利です。また、パフォーマンス問題ですが、バグのある、または効率が悪い自家製アルゴリズムを使用して、正規表現ライブラリに勝つことを望まない場合があります。

それに加えて、正規表現が不当に批判される多くの理由があります。

  • 正規表現は効率的ではありません。上位のものを作成することは明らかではないためです
  • 一部のプログラマは、何度も使用される正規表現を1回だけコンパイルすることを「忘れる」(Javaの静的パターンのように)
  • 一部のプログラマーは試行錯誤を繰り返します -正規表現を使用するとさらに効果が低下します!

4

私が思うに、正規表現を学び、正規表現を維持することは不評であり、ほとんどの開発者は怠惰であるか、ほとんどの開発者は外部ライブラリに依存して解析を行っています...問題の完全なコード。しかし、正規表現を実装または変更/保守する場合、失敗するだけです。

「友達はHTMLを解析するために友達に正規表現を使用させないでください」という人気の格言があります。

しかし、私が懸念している限り、私はRegexを使用して完全なHTMLパーサーを作成し、regexは速度とメモリの両方でHTML文字列を解析する方が優れていると感じています(達成したいことを考えている場合:))


2
ほとんどの開発者を怠惰に書くのは不誠実だと思います... 構文は非常に不可解で、直感的ではなく、初心者にとっては落とし穴がたくさんあると思います。これは、高い参入障壁につながります。同じ理由で、Perlは多くの人に「悪い」評判がありますが、非常に強力な言語でもあります。シンボルを知る前に数式を読もうとするようなものです。それは困難なことであり、開発者はその構文を学習することで利益を得られることを知るために、自分たちの時間について司法的でなければなりません。
Katastic Voyage 2018

あなたはなります HTMLが正規言語ではないので、HTMLでのエッジケースを欠場します。HTMLの既知のサブセットを解析することを意図している場合は安全です
Boyang

2

正規表現は、私を含む多くの人々にとって深刻な謎です。うまく機能しますが、それは数学の方程式を見るようなものです。誰かが最終的にhttp://regexlib.com/でさまざまな正規表現関数の統合された場所を作成したことを報告します。マイクロソフトが、文字の削除や日付のフィルタリングなどの一般的な処理の多くを自動的に実行する正規表現クラスのみを作成する場合は、


2
あなたは要点を逃しています。正規表現の考え方は、学習にいくらかの時間を費やすことであり、習得したら、魔法のような「日付を読む」クラスは不要になります。代わりに、正規表現はほとんど必要ありません。さらに、「yyyy / mm / dd」用に1つ書き込むのと、「mm-dd-yyyy」用に1つ書き込むのと同じくらいの労力で、「mm-yyyy / dd」用に1つ書き込むこともできます(これにより、頻繁には起こりませんが、魔法のクラスでは決してできないことを実行する方法の例です」
Jasper

1

正規表現が非常に貴重な場合があります。「あいまい」検索を実行する必要がある場合。データが変化し、特定のランダム性がある場合。ただし、単純な検索と置換、または文字列の確認を行う必要がある場合は、正規表現を使用しません。私はそうする多くの人々を知っていますが、彼らはそれをすべてに使用します。それは論争です。

壁に鋲を付けたい場合は、ハンマーを使用しないでください。はい、うまくいきますが、ハンマーを手に入れるまでに、壁に20本の鋲を置くことができました。

正規表現は、それらが設計された目的に使用する必要があり、それ以上のものは使用できません。


0

正規表現は不可欠なツールだと思いますが、それらの最も厄介なことは、さまざまな実装があることです。構文、修飾子、および特に「貪欲」のわずかな違いは、物事を非常に混乱させ、試行錯誤を必要とし、時には不可解なバグを生成する可能性があります。


正規表現の実装は、あなたが「貪欲」と呼んでいる最大のマッチングへのアプローチがどのように異なるのでしょうか。あなたは違いを意味してください左端-最長最長左端のセマンティクスを?それが私が知っている唯一の違いです。つまり、貪欲が熱意よりも優先されるか、その逆かです。
tchrist 2010年

0

場合によってはそれらを使用する必要があると思います。たとえば、字句解析器を構築します。

私の意見では、これは正規表現を書ける人と書けない人(またはほとんどない人)の視点です。個人的には、これは、たとえば、ユーザーに警告するためのJavaScriptやサーバー側の言語など、フォームの入力を有効にするのに適していると思います。


0

プログラマーの間ではあまり知られていないテクニックだと思います。そのため、広く受け入れられていません。また、コードをレビューしたり、作業をレビューしたりする技術者以外のマネージャーがいる場合、正規表現は非常に良くありません。あなたは完全な正規表現を書くのに何時間も費やし、モジュールがほんの数行のコードを書いたと考えて、モジュールにいくつかのマークが付けられます。また、他のところで述べたように、正規表現を読むことは非常に難しい作業です。


1
正規表現の読み取りは、それらを作成したプログラマが空白、コメント、英数字識別子、およびおそらく実行遅延を介して埋め込まれたサブルーチンの使用に失敗した場合にのみ困難な作業になります。つまり、一般的なプログラミングに適用できるすべてのソフトウェアエンジニアリング手法は、正規表現でも従う必要があります。これらの原則が無視された場合、ライターはプロ用のコードを作成していません。
tchrist 2010年

あなたのマネージャーは、「プログラミングの本当のヒーローはネガティブなコードを書く人だ」とは知らないと思います。
Rajeev 2011年

マネージャーが3行のコード(正規表現を含む)で仕事を達成したと言って、900行のアセンブラーでそれを行った何者かを称賛している場合...新しい仕事を見つけることをお勧めします。
Phil Perry

0

コンパイラーの定義にlexやyaccで使用されているような適切な正規表現システムは、非常に便利でクリーンです。これらのシステムでは、式のタイプは他のシステムに関して定義されます。これは、perlやsedコード(など)で一般的に見られる、おかしな形式の判読不能なラインノイズの巨大な1行正規表現であり、「物議を醸す」(ゴミ)ものです。


-4

正規表現の最も有効で通常の使用法は、電子メールアドレス形式の検証です。

それはそれの良い応用です。

TextPadで1回限りの正規表現を何度も使用して、フラットファイルのマッサージ、csvファイルの作成、SQL挿入ステートメントの作成などを行ってきました。

よく書かれた正規表現は遅すぎてはいけません。通常、Replaceへの大量の呼び出しのような代替手段は、はるかに遅いオプションです。ワンパスでそれを行うかもしれません。

多くの状況では、正確な正規表現のみが必要です。

特殊な非印刷文字を無害な文字に置き換えることも、別の良い使い方です。

もちろん、保守性を損なうために正規表現を使いすぎるコードベースがいくつかあると想像できます。私自身、それを見たことがありません。私は実際には正規表現を十分に使用していないため、コードレビューアに避けられています。


10
経験から、正規表現は実際には電子メールアドレスの形式を検証するためのかなり貧弱なツールであることがわかっています。正規表現として実装された本当に完全な形式のバリデーターは数百文字の怪物ですが、ほとんどの人が作成に5分かかる短い「十分な」バリデーターのほとんどは、有効で配信可能なアドレスの大きなカテゴリを拒否します。
Dave Sherohman、2009

おいおい 私は「十分に良い」と話していました。理論的には大きなスワスは大きいかもしれませんが、このような短い表現で得られるカバレッジの割合を考慮してください。私も怪物を見てきましたが、あなたのエレガントな代替手段は何ですか?
Chris Morley、

2
\ w @ \ w +。\ w +のようなものを使用して、速度が重要であり、いくつかの誤検知または誤検知は重要ではないファイルの巨大なディレクトリで電子メールアドレスをすばやく検索しました。しかし、電子メールアドレスを検証する最良の方法は、電子メールをそのアドレスに送信することです。
RossFabricant 2009

ええメールアドレスの仕様は厄介な混乱です。stackoverflow.com
questions / 611775 /…

@ Nick、@ Dave:メールアドレスの検証は厄介な混乱である必要はありません。
tchrist
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.