web-dev-qa-db-ja.com

正規表現対。文字列の解析

ワームの缶を開けて反対票を獲得するリスクがあるので、私は尋ねる必要があると思います、

いつ正規表現を使用する必要があり、いつ文字列解析を使用する方が適切ですか?

そして、私はあなたのスタンスに関して推論を必要とするでしょう。 readabilitymaintainabilityscaling、そしておそらくあなたの答えの中のほとんどすべてのperformance

私は別の質問を見つけました ここ 例を挙げてさえわずらわしい答えが1つしかありませんでした。これをもっと理解する必要があります。

私は現在C++で遊んでいますが、正規表現はほとんどすべての高水準言語にあり、さまざまな言語が正規表現をどのように使用/処理するかについて知りたいのですが、それは後回しにしています。

理解してくれてありがとう!

編集:私はまだより多くの例を探しており、これについて話しますが、これまでのところ反応は素晴らしかったです。 :)

34
Dan

それはあなたが扱っている言語がどれほど複雑かによって異なります。

分割

これは機能する場合に最適ですが、エスケープ規則がない場合にのみ機能します。たとえば、引用符で囲まれた文字列内のコンマは適切な分割ポイントではないため、CSVでは機能しません。

foo、bar、baz

分割できますが、

foo、 "bar、baz"

できません。

定期的

正規表現は "regular grammar" を持つ単純な言語に最適です。 Perl 5の正規表現は、後方参照のために少し強力ですが、一般的な経験則は次のとおりです。

大括弧((...)[...])またはHTMLタグのような他のネストに一致させる必要がある場合は、正規表現だけでは不十分です。

正規表現を使用して、文字列を既知の数のチャンクに分割できます。たとえば、日付から月/日/年を引き出します。しかし、これらは複雑な算術式を解析するための間違った仕事です。

言うまでもなく、正規表現を書き、一杯のコーヒーを飲みに戻って戻ってきて、書いたばかりの内容を簡単に理解できない場合は、自分がやっていることをより明確に表現する方法を探す必要があります。 メールアドレス は、おそらく正規表現を使用して正しく読みやすく処理できる限界にあります。

コンテキストフリー

nestingを処理してtreeまたは 演算子の優先順位 または結合性を扱います。

多くの場合、コンテキストフリーパーサーは正規表現を使用して入力をチャンク(スペース、識別子、句読点、引用符付き文字列)に分割し、次に文法を使用してチャンクのストリームをツリー形式に変換します。

CF文法の経験則は

正規表現では不十分だが、言語内のすべての単語が前の宣言に関係なく同じ意味を持つ場合、CFは機能します。

非コンテキストフリー

あなたの言語の単語が文脈によって意味を変えるなら、あなたはより複雑な解決策を必要とします。これらはほとんど常に手作業でコーディングされたソリューションです。

たとえば、Cでは

#ifdef X
  typedef int foo
#endif

foo * bar

fooが型の場合、foo * barfooという名前のbarポインターの宣言です。それ以外の場合は、fooという名前の変数とbarという名前の変数の乗算です。

32
Mike Samuel

正規表現AND文字列解析 ..である必要があります。

あなたはそれらの両方を有利に使うことができます!多くの場合、プログラマーはテキストを解析するために単一の正規表現を作成しようとし、それを維持するのが非常に難しいことに気付きます。必要に応じて、両方を使用する必要があります。

REGEXエンジンは[〜#〜] fast [〜#〜]です。単純な照合には1マイクロ秒もかかりませんが、HTMLの解析には推奨されません。

8
Anirudha