0

Composed Regular Expressionsに関して Martin Fowler がまとめた記事を読んでいました。これは、次のようなコードを使用できる場所です。

const string pattern = @"^score\s+(\d+)\s+for\s+(\d+)\s+nights?\s+at\s+(.*)";

そして、それを次のようなものに分割します。

protected override string GetPattern() {
      const string pattern =
        @"^score
        \s+  
        (\d+)          # points
        \s+
        for
        \s+
        (\d+)          # number of nights
        \s+
        night
        s?             #optional plural
        \s+
        at
        \s+
        (.*)           # hotel name
        ";

      return pattern;
    }
  }

またはこれ:

const string scoreKeyword = @"^score\s+";
const string numberOfPoints = @"(\d+)";
const string forKeyword = @"\s+for\s+";
const string numberOfNights = @"(\d+)";
const string nightsAtKeyword = @"\s+nights?\s+at\s+";
const string hotelName = @"(.*)";

const string pattern =  scoreKeyword + numberOfPoints +
  forKeyword + numberOfNights + nightsAtKeyword + hotelName;

またはこれでも:

const string space = @"\s+";
const string start = "^";
const string numberOfPoints = @"(\d+)";
const string numberOfNights = @"(\d+)";
const string nightsAtKeyword = @"nights?\s+at";
const string hotelName = @"(.*)";

const string pattern =  start + "score" + space + numberOfPoints + space +
  "for" + space + numberOfNights + space + nightsAtKeyword + 
   space + hotelName;

これは簡単に実行できるように思えますが、いくつかの利点があるかもしれません。私は決して「正規表現の男」ではなく、自分で作成するのに時間をかけるのではなく、必要な正規表現を見つけるためにネットを検索することがよくあります。特定の問題にぴったりの正規表現を見つけたので、それをコピーして貼り付け、テストして、宣伝どおりに機能することを確認します。次に、それが何をするかを説明するコメントをドロップするかもしれません。しかし、その後、私は人生でより大きく、より良いものに向かいます.

マーティン・ファウラーの議論で説明されている方法で正規表現パターンを分割すると、実際にコメントよりも理解しやすくなるかどうか疑問に思っていますか? 結局のところ、コードにはいまだ醜い正規表現が残っていますが、それは多くの部分に分かれています。その式を拡張する必要がある場合...これは、正規表現が何をしているのかを本当に理解するのにどのように役立ちますか?

根っからの perl 連中が正規表現パターンを愛していることは知っています。しかし、他のすべてのプロジェクトで 1 回以上正規表現を扱わない人 (質問) にとって、正規表現パターンをより小さなビットに分割することは、多かれ少なかれ読みやすいと思いますか? プロジェクトでこの概念を採用し、有用だと感じた人はいますか? ...役に立たない?

4

3 に答える 3

2

そのとおり。正規表現は強力ですが、構文が簡潔なため、非常に読みにくくなっています。「これはURIと一致します」などのコメントを読んだとき、それがどのように行われるかを実際に理解するのに役立ちません。たとえば、あいまいなコーナーと一致しないバグを修正する必要があります。クエリ文字列の大文字と小文字を正しく区別します。正規表現はコードです。関数を文書化するのと同じように文書化します。短くて(合理的に)明確な場合は、正規表現全体に対する1つのコメントで問題ありません。複雑な場合は、個々の部分を明確に強調してコメントします。本当に複雑な場合は、いくつかの正規表現に分割してください。

于 2009-07-24T23:43:01.377 に答える
0

拡張構文があれば、かなり読みやすいです。

/^
  score   \s+ (\d+) \s+
  for     \s+ (\d+) \s+
  nights? \s+  at   \s+ (.*)
/x

私は個人的にPerl6スタイルの正規表現を好みます。読みやすいと思います。

rule pattern{
  score        $<score>= [ <.digits>+ ]
  for          $<nights>=[ <.digits>+ ]
  night[s]? at $<hotel>= [ .+ ]
}

そのルールに対して一致を実行する$/と、一致したテキストに関連付けられます。

だからこのようなもの:

say "Hotel $/<hotel>";
say $/.perl;

このようなものを出力します

Hotel name of hotel
{
  'hotel'  => 'name of hotel',
  'nights' => 5,
  'score'  => 8
}
于 2009-07-25T01:05:48.803 に答える
0

PHP では、連想配列と PHP のバージョンの tr 関数を使用してこれに対処しています (どの言語にも同様のデータ構造と関数が存在すると想定しています)。

配列は次のようになります。

$mappings = array ( 
  'a' => '[a-z0-9]',
  'd' => '[0-9]', 
  's' => '\s+', //and so on 
);

次に、それらを使用するときは、 tr 関数とマージするだけです。マップされたものは変換され、マップされていないものは失敗します:

 $regexp = strtr( $simplified_string, $mappings) ;

このアプローチは、物事を単純化するのと同じくらい簡単に物事を複雑にしすぎる可能性があることに注意してください。あなたはまだパターンを書いています。それは、あるパターンを別のパターンに抽象化しただけです。それにもかかわらず、これらの貧弱な文字クラスを持つことは、言語を話さない開発者または仕様プロバイダーに正規表現をアウトソーシングするのに役立ちます。

于 2009-07-25T01:28:29.567 に答える