正規表現のコメント


11

正規表現にコメントするための一般的な慣行はありますか:正規表現の別の部分を参照するインラインコメントまたはすべての表現に対する一般的なコメントですか?


2
ありますが、より具体的にする必要があります。たとえば、Bashはインラインコメントをサポートし、Pythonは詳細な正規表現を提供します。
サキスク

6
正規表現に関する私の経験則は、正規表現にコメントする必要がある場合、複雑すぎることです。
zzzzBov

1
常にこのリンクを含めてください:regexcrossword.com
Kieveli

あなたがそれをコメントしなければならないなら、それがあまりにも複雑であることに必ずしも同意しません。複雑な正規表現を使用しても、目を見張るような命令コードを大量に節約できます。適切な記述変数名を使用して、正規表現を割り当てます。それでもまだ明確でない場合は、簡単なコメントを使用して、正規表現の背後にある元の意図を伝えてください。
クレイグ14

回答:


10

私の考えでは、良い表現は正規表現の一般的な考え方が何であるかをコメントで簡潔に述べることです。これにより、他の開発者(または場合によっては自分自身)がRegExrなどのパーサーに正規表現をコピーアンドペーストする手間が省けます。


2
とにかく、RegExrは、devが正規表現に精通していない限り発生します。しかし、一般的な説明を提供することに同意します。それが正規表現で私がすることです。
ロバートハーヴェイ

3
+1:より詳細なものはすべて、コメントとして正規表現のクラッシュコースになります。
マット

この答えと@zzzzBovのコメントは理にかなっています。
m0nhawk

1
正規表現を理解するための退屈な検査の手間を省くだけでなく、特に最初のプログラマーが最初の時期に正規表現自体を間違えたという明確な可能性を考えると、元のプログラマーの意図を明確にします。そうは言っても、多くの場合、正規表現を適切な変数名に割り当てることは、意図を適切に文書化するのに大いに役立ちます。
クレイグ14

9

これは言語固有の回答ですが、質問には言語は記載されていません。

「Dive Into Python」という本は、Verbose Regular Expressionsを使用してコメントを実装することを提案しています。

Pythonでは、冗長な正規表現と呼ばれるものを使用してこれを行うことができます。詳細な正規表現は、次の2つの点でコンパクトな正規表現と異なります。

  • 空白は無視されます。スペース、タブ、およびキャリッジリターンは、スペース、タブ、およびキャリッジリターンとして一致しません。それらはまったく一致していません。(詳細な正規表現でスペースを一致させたい場合は、その前にバックスラッシュを入れてエスケープする必要があります。)
  • コメントは無視されます。詳細な正規表現のコメントは、Pythonコードのコメントとまったく同じです。#文字で始まり、行末まで続きます。この場合、ソースコード内ではなく複数行の文字列内のコメントですが、同じように機能します。

例:

>>> pattern = """
^                   # beginning of string
M{0,4}              # thousands - 0 to 4 M's
(CM|CD|D?C{0,3})    # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
                    #            or 500-800 (D, followed by 0 to 3 C's)
(XC|XL|L?X{0,3})    # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
                    #        or 50-80 (L, followed by 0 to 3 X's)
(IX|IV|V?I{0,3})    # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
                    #        or 5-8 (V, followed by 0 to 3 I's)
$                   # end of string
"""
>>> re.search(pattern, 'M', re.VERBOSE)                1

ソースと詳細はこちら

このメソッドには、呼び出し側がパターンが冗長形式で記述されていることを認識し、それに応じて呼び出す必要があるというわずかな欠点があります。


2
パターンを変数に保存するのではなく、パターンre.compileを定義した時点で使用し、結果のオブジェクトのみを保存できます。そうre.VERBOSEすれば、パターンコンパイルフラグ(を含む)をパターン自体から分離する必要がありません。
ジョンバーソロミュー14

本当に役立つ答え、ありがとう!しかし#、冗長フラグを使用している場合、どのように一致させることができますか?ちなみに、ソースリンクはダウンしているようです。
winklerrr

さて、#文字クラス内で文字通り一致することができます:([#]ソース:docs.python.org/3/library/re.html#re.X
winklerrr

8

通常、正規表現を作成し、正規表現の個々の部分についてではなく、その目的を説明します。それが何で、なぜですか。これは、「私のコメントはどのように見えるべきですか?」「コードが何をしているのか書いてはいけない、なぜコードが何をしているのか書いて

// Strip the leading "?" and remove the query parameters "offset=<integer>" & "count=<integer> so we have a pattern of the request"          
var search = location.search.substring(1).replace(/offset=[0-9]+?&/g, "").replace(/count=[0-9]+?&/g, "");

コード内のコメントを介して正規表現について誰かに教えようとしているのでない限り、個々のピースが何をするのかを説明するとは思わない。他のプログラマーと作業する場合、グローバルな正規表現として何かを知っていると安全に想定できます。


3
あなたは...驚かれることでしょう
マット

6

正規表現をどのように組み合わせているかによります。一般的に言えば、実際の正規表現文字列自体にコメントを入れるのは悪い考えだと思います(私の知る限り、ほとんどのシナリオでは不可能です)。正規表現の特定の部分を本当にコメントする必要がある場合(誰かに教えようとしていますか?)、各チャンクを独自の行で個別の文字列に分割し、プログラミング言語の通常のコメントプロセスを使用して各行をコメントします。そうでなければ、pleinolijfの答えはかなり良いです。

例:

string myregex = "\s" // Match any whitespace once
+ "\n"  // Match one newline character
+ "[a-zA-Z]";  // Match any letter

4

通常、正規表現の全体的な目的を説明する名前の文字列定数を定義します。

例えば:

const string FloatingPointNumberPattern = @"[-+]?[0-9]*\.?[0-9]+";

この定数の上にコメントを追加して説明を加えることもできますが、通常は定数名自体で十分です。


1
この答えのように1つの余分なもの、私はそれが複数の場所で使用されます場合は、意図があることを持っていないことをコメントする何の忘却を-あまりにも周りに運ばれます。
Jトラナ14

3

いくつかのシナリオでは、開発者は正規表現を使用して、典型的なドメイン外のテキストと一致する場合があります。元の開発者は、その反復プロセスによってのみ発見された可能性のあるさまざまなエッジケースをキャプチャする多くの反復を行った可能性があります。したがって、後続の開発者は、一般的なケースを認識していても、元の開発者が扱った多くのエッジケースを認識しない場合があります。

このような場合、バリエーションの例を文書化する価値があるかもしれません。このドキュメントの場所は、量によって異なる場合があります(たとえば、必ずしもコード内にあるとは限りません)。

アプローチする方法の1つは、将来の開発者は正規表現の仕組みなどの基本的な知識のみを持ち、(1)必ずしも知られていない正規表現の開発前に持っていた知識はないと仮定することです将来の開発者、または(2)開発中に得た知識(発見されたエッジケースなど)。

たとえば、開発中に「ああ、Xがこの形式をとることを知らなかった」などと言ったら、それを文書化する価値があります(おそらく、そのバリエーションを処理する正規表現の一部)。


2

コメントには、コードから明らかでない有用な情報を追加する必要があります。

  1. コード自体またはコメントのいずれかで、要件レベルで式が何を行うかを理解しやすくします。式の背後にある意図は、電子メールアドレスを検証するか、カナダの電話番号を選択することです。
  2. 式が実際に何をしているか、つまり式が何を評価するかを理解しやすくします。最初に式を分割して明確にするようにしてください。最初にすべてのハイフンをチェックしてからすべての数字を削除し、中間値を保持する変数を持つ2つの部分の式を作成すると、読みやすくなり、読者は一度に1ステップずつロジックをステップ実行できます。(ビット操作 '>>'を含む古いコードを解読しようとし、特定のフラグが設定されているかどうかを調べる、SEの質問に対する有名な答えがあります。答えがコードの実際の動作だけでなく、質問の真価は、将来この種のコードを分解することになるはずです。これはまさに私が説明しようとしていることですが、できます」

最後のサイクルごとに必要なアプリケーションはほとんどありません。大量のデータセットをパターンマッチングしている場合は、おそらくもっと良い方法があるかもしれませんが、ほとんどの場合、余分な実行時間はそれほど重要ではありません。

そして、あなたのコードに出会ってバグを修正する次の人が6ヶ月であなたになるかもしれないことを思い出してください。あなたがそれが何をすべきかを思い出す方法はありません。


1

RegExを別のクラスに抽出して、意味のある名前を付けます。その後、自動テストでコードを文書化します。

これにより、

  • コードが実際に機能すること-コーナーケースの場合も
  • 迅速な「バグ修正」が多くのコーナーケースを台無しにしないようにします
  • バックトラッキングが無効になっている場合の最適化を文書化できます

当然、クラスはいくつかの正規表現をホストする場合があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.