web-dev-qa-db-ja.com

正規表現を行うより良い方法は?

正規表現は本当に嫌いです。正規表現に戻るたびに、再学習する必要があるようです。また、メンテナンス、変更、一目でそれが何をしているのかを理解することは非常に困難です。

よりセマンティックな「sql like」ステートメントを正規表現に変換する別のレイヤーを作成しようとした人はいますか?私はそれが次のように機能すると想像します:

AnotherString = "coffee hello beep 15"

FindString.StartsWith string longer than 5
FindString.Contains "beep" after "hello"
FindString.EndsWidth int < 20
FindString.DoesntContain "no!!" and DoesntContain "what!"
Foreach FindString match in AnotherString
    ...
Next

これはおそらくこれまでで最も優れた例ではありませんが、パターンは、伝統的な正規表現に分解できる意味のある意味のある言語でパターンが構築されているという考えです。上記は、開発者が変更する方がはるかに簡単です。私はある程度SQL/Linqのようなものだと思います。

それは正規表現をより意味的で保守可能にします。これは以前に試されたことはありますか?これを試すのは悪い/良い考えですか?うまくいきますか?

編集

おそらくこれはより良い例です(URLは解析が難しいことで有名ですが、これは非常に単純化されています)。

string UserInputtedURL = "http://www.google.com/page.html?ID=5"

Protocols = {"http", "https"};
Domains = {"com", "net", "org"}
Rule.CaseSensitive = false;
Rule starts with Protocols OR starts with "www";
Rule followedby string endson "."
Rule followedby Domains
Rule if stringend or endswidth " " end else continuewith Ruleset2

RuleSet2.startswith "/"
etc...

if(UserInputtedURL.Matches(Rule)){
    // URL is valid!
}
8
Tom

これは、少なくともPerlではすでに行われています。

参照 http://search.cpan.org/~chromatic/Regexp-English-1.01/lib/Regexp/English.pm

実際に世界を席巻しているわけではありませんが、別の言語で同様のメカニズムを記述したい場合は、これが良い出発点になる可能性があります。

RegExesの基本を理解するのはそれほど難しくありません。方言の切り替え(EmacsとPerl互換の正規表現との違い、たとえばVisual Studioの[検索]ダイアログの変なバリエーション)が最大の問題だと思います。 「平易な英語」バージョンを学ぶ気にはならないでしょう。一般的に使用される記号の自然言語への翻訳も不完全であるため、抽象化を受け入れるのはほとんど簡単です。

8
JasonTrue

正規表現の主な目的は、通常の言語(ルールに基づいて文字列を照合するIOW)を記述するステートメントを作成するための簡潔な表記を提供することです。このような簡潔な表記を生成する詳細な表記は、基本的にRube Goldbergデバイスです。

また、次の場合:

一部の人々は、問題に直面したときに「わかっている、私は正規表現を使用する」と思います。今、彼らは2つの問題を抱えています。 —ジェイミー・ザウィンスキー

あなたは次のことをしているようです:

一部の人々は、正規表現を使用することに直面したときに、「わかっています。正規表現を生成する言語を書きます」と思います。

ここで3つの問題があります。

25
Rein Henrichs

あなたが提案するのは、信じられないほど冗長です。正規表現は、間違って行うと消化が難しく、一部しかかかりません(少しだけですが、正規表現の読み取りや書き込みはめったにありませんが、最も重要な機能(繰り返し、文字クラス、先読み)の構文は覚えています。 )そして、これらの機能を使用して正規表現を比較的流暢に読むことができます)慣れてきたら、このようなものよりも、いくつかの文字で完全にうまく表現できるものの完全な疑似英語文を入力する必要があります。このような言語の実装の複雑さ(およびエラーが発生しやすいこと)も考慮してください。

私が提起しなければならないもう1つの問題:例として使用するチェックには、正規表現を使用して実行することは完全に不合理なものが含まれます-整数で終了するのは簡単ですが、 数値の比較は正規表現を使用することはできません 。また、これらのテストの多くは、プログラミング言語のネイティブな文字列処理ツール(たとえば、長さをチェックしたり、文字列が長くなったり動的になったりした場合の部分文字列チェック)で簡単に記述できます。正規表現が存在し、有用であるという事実は、すべての文字列処理にそれらを使用する必要があることを意味しない場合があります。注意して使用してください。すべて問題ありません。

6
user7043

人間にとって単純なことは、コンピュータにとって際限なく複雑です。

ほぼAppleScriptで記述している構文とその構文のように、AppleScriptは一般に嫌われています。それをよく知っている人でも、構文は簡単で読みやすいように見えるかもしれませんが、その冗長性は、あなたが毎日忘れない限り、その落ち込みです。すべての文法とキーワードルール。正規表現構文と同様に不透明になります。冗長性のために初心者が理解するのは難しく、その冗長性のために専門家にとっては難しい。

あなたの不自然なストローマンの例:

Rule followedby string endson "."

followed byまたはfollowedbyまたはafterまたはbeforeまたはprecedesまたは代わりにprecedingを使用することを覚えている方法他の何かを「追いかける」という概念の数十の英語の代替案の1つ。同じロジックをendsonに適用できます。これはendswithまたはendingwithまたはendingの場合もありますが、使用するにはチートシートまたはブックが必要です。提案された構文。

5
user7519

確かに機能しますが、最も基本的な表現以外のものを考慮すると、ものすごく実装するのが(imho)困難になります。

正規表現は、独自の言語です。それがどのように機能するかを理解したら、それを忘れないでください(構文の復習が必要な場合がありますが、それはすべての言語で同じです)、ラッパーは不要になります(追加のオーバーヘッドは不要になります)。

Mastering Regular Expressions (O'Reilly)を読むまで、私は(やや)あなたのように思っていました。私はそれを拾うことを強く勧めます。

3
Demian Brecht

必要なのは、正規表現を作成するためのDSLです。これはそれほど難しいことではありません。グループをキャプチャするためのフラグ、頻繁に使用される文字クラスの特別なコード、アンカーなどによってのみ、複雑/冗長になります。

基本は次のとおりです。

  1. 単一の文字は正規表現です。
  2. rが正規表現の場合、begin r endも正規表現です。
  3. R1とr2が正規表現の場合、r1 then r2は正規表現です
  4. R1が正規表現で、nが整数で、mが整数またはmanyの場合、r1 fór n to m は正規表現です
  5. R1とr2が正規表現である場合、r1 or r2は正規表現です。

もちろん、次のように省略したいと思うでしょう。

'h' then 'e' then 'l' then 'l' then 'o'

"こんにちは"

同様に、このDSLをしばらく使用した後、

\s*

の代わりに

begin ' ' or '\t' or '\r' or '\n' end for 0 to many times

以下は興味深いです:私たちのものとまったく同じパラレルユニバースがあるかもしれませんexcept正規表現が導入されており、上記のような詳細なDSLで一般的でした。そして、このユニバースのstackexchange.comで、なぜ正規表現がそれほど不器用である必要があるのか​​と尋ねる人がいるかもしれません。彼/彼女は、簡潔だが同等に強力な表記法を発明することにより、正規表現での作業をはるかに簡単にする良いアイデアを持っていた...

2
Ingo

正規表現を行う最善の方法は、それらを学習して理解するか、まったく使用しないことです。正規表現を学習しない言い訳として他のツールを使用することは、正規表現に遭遇するたびにそれらを再「学習」する必要があることを意味します。

正規表現を深く学ぶために1日(たった1日)を費やしてください。そうすれば、キャリア全体を活用できる新しいツールが提供されます。また、それらが適切である場合、さらに重要なこととして、適切でない場合についても理解を深めることができます。

1
Bryan Oakley

正規表現に代わるものは Backus-Naur Form であり、EBNFやABNFのような人間によるバリエーションもいくつかあります。大まかに言って、文法の各部分は「プロダクションルール」に分割され、左側に非終端記号の定義があり、右側に規則を記述する一連の終端記号と非終端記号があります。あなたの例は、BNFでは次のようになります。

expr ::= startword "hello" "beep" endword
       ;

startword ::= Word_CHAR Word_CHAR Word_CHAR Word_CHAR Word_CHAR 
            | startword Word_CHAR
            ;

endword ::= DIGIT
          | "1" DIGIT
          ;

また、BNFはたまたまcontext free言語を表現します。これは、正規表現が記述する正規言語の適切なスーパーセットです。

Ruby Regexp Generator http://www.rubyregexp.sf.net は、詳細な定義を指定できるため便利ですが、あなたのコードのための正規表現。私はそれを松葉杖のように使用して、スタンドアロンのソリューションとしてではなく、私の正規表現を構築するのを助けます。

0
V9801