正規表現を改善する

正規表現(以降RVと略します)に関する本を読んだ後、読みやすさについて考えました。 RVが登場したばかりで、\ d、\ wなどの記号がかなりあった場合、恐らくすべてがそれほど怖くはありませんでしたが、それでも視覚化について考える価値はありました。 現在、PBからコードを読み取ることは静かな恐怖です。 いいえ、PBが短い場合、特別な問題はありませんが、より複雑になり、さまざまな括弧が表示されるため、すべてが単に悪夢になります。 状況によっては、一部の言語(指を向けない)で常にスラッシュを2重にしなければならないという事実によって悪化しています。



さらに、現在ほとんどのプログラミング言語で使用されているRV表記法では、一見単純に見える状況でも、さまざまなフェイントを使用して脱出する必要があります。 頭に浮かんだ最初の例は、「abc」ではなく「xyz」の場合に正規表現を作成することです。







私の意見では、現在使用されている表記法を放棄し、通常のプログラミング言語により近い新しい表記法を作成する時が来ました。RV表記法は本質的に言語ですが、設計上はひどいためです。 今日の表記で最悪なのは、 (...)(:...)(?:...)(?= ...)(?!...)のような括弧の豊富さです (?<= ...)(?<!...)(?<) 。 彼らのおかげで、表現が混乱し、探しているものをすぐに言うためにすべてのRVの視線をキャプチャすることはできませんが、たとえば、RVの中央の^が行の始まりであり、角かっこの始まりであることを忘れずに、行のすべての文字をチェックする必要があります^ ...]は反転です。 間違っているのは、新しい機会が生じたときに、開発者が新しい指定(&^%$#@ ...)を作成するということです。それ自体は何も言いません。



結局のところ、通常のプログラミング言語の魅力は何ですか(極端な場合を除いて)? なじみのない言語でifまたはwhile ステートメントが表示された場合 、それが何かをしているとすぐに言うことができます。 はい、これらの演算子をそれぞれ@#$%や#&$ ^のような文字に置き換えることができますが、慣れることもできますが、ジョージア州のロシア語のレッスンについての冗談で「これは覚えておく必要があり、これを理解することはできません。」



おそらく賢明なコードエディターによって状況が改善された可能性があります。正規表現では、アクションの領域をすぐに確認するために、括弧(?:...)(?= ...)などが異なって強調表示されます。ほとんどのプログラミング言語では、これはほとんど不可能です。 RVには行があり、エディターはその行の内容によってその前にあるもの(RVまたはプレーンテキスト)を判断できるはずです。 とにかく、ブラケットの大きな入れ子で、PBはマルチカラーの虹に変わります。



一般的に言えば、RSの読みやすさに関しては、RSが複数の行に記録されているときのモードの出現と、RS内のコメントのおかげで、すでにかなりの変化が生じています。 明確なビュー(?の場合)のデザインでさえ、Perl(夜間には言及されません)では、プログラムコードを正規表現に埋め込むことができ、.NETでは、PBによる単純な置き換えの代わりに、置き換えられた値を生成できます 特別に訓練された 特別なデリゲート。 一般的に、多かれ少なかれ理解しやすいRVを作成することはすでに可能ですが、とにかくそれは松葉杖に似ています。



Brainfuckではなく、他の「人間」のプログラミング言語に似たRV言語を作成します。 次に、その中で、理解可能なバックライトを整理し、IntelliSenseを起動し、将来、PBの段階的なデバッグを行うことができます。



さらに、RVを見たいものを示したいと思います。



まず、通常の文字列からPBを何らかの形で分離する必要があります。 関数が機能するために文字列を正確に必要とすることは明らかです。Perlで行われているように、RVを言語自体に埋め込む必要があるかどうかはわかりませんが、文字列のままにしておきますが、引用符内で強調表示するには、追加の表記を使用する必要があります たとえば、 「\ d \ w」の代わりに何でもかまいません(明確にするために、スラッシュを2つ重ねません) 。「!\ D \ w!」を使用する価値があります。 または"<\ d \ w>"の場合、エディターはPBと行を簡単に区別できます。 将来的には「!...!」というエントリを使用しますが、これは重要ではありません。他の表記法と同様に、要点です。



第二に、RTはスペースと改行が無視されるモードでのみ記述されるべきであり、RTの構成から常に変更されない式内のリテラルを分離するために、リテラルは引用されます(何があっても)。 たとえば、 「abcd \ d \ wxyz」の代わりに、次のように記述できます。



"! 'abcd'

\d\w

'xyz'

!"









または、「! 'Abcd' \ d \ w 'xyz'!」



ここのコードエディターは、 abcdxyzを別々に着色できます。 これらの部分をリンクするには、「+」記号を使用する価値があります。 さらに明確になります: 「! 'Abcd' + \ d \ w + 'xyz'!」 なぜなら PBの個々の部分はより視覚的に分離されています。



「+」記号が値「1回以上の一致」で使用されるようになったと混乱するかもしれませんが、この値では他の誰も使用しないので、これは怖いことではありません。 これは論理的ではありません。 {min、max}のような視覚的な構造があります。それらを「*」演算子と一緒に使用してみましょう。 演算子「*」は、「乗算」の意味でのみ使用する必要があります。つまり、式「! 'Abc' * 3!」です。 文字列「abc」を3回繰り返す必要があることを意味します。 PB "! 'Abc' * {1、3}!" 「abc」を1〜3回繰り返す必要があることを意味します。 同様に、エントリ「! 'Abc' * {1、}!」を使用できます 「+」の代わりに「1回以上の一致」の値に、演算子の代わりに*書き込み: 「! 'abc' * {0、}!」 。 エントリ「! 'Abc' * {3、3}!」 すでに見た「! 'abc' * 3!」に相当 。 古い演算子「*」は、式「! 'Abc' * {、}!」に置き換えられます。



おそらく、中括弧の代わりに、角括弧または丸括弧を使用する価値があります。そうすれば、セグメントと間隔の数学表記にさらに近づくでしょう。



問題は、最小演算子「*」の表示方法にあります(貪欲ではありません)。 除算演算子を使用することもできますが、これも論理的ではないため、 「! 'Abc' min * 3!」という形式で直接記述できます 。 ここで、 min *はスペースのない単一のステートメントです。 私はこの録音オプションはあまり好きではありませんが、少なくともそれ自体の名前で本質を説明しています。



ほとんどのブラケットは組み込み関数に置き換える必要があります。 たとえば、「[abc]」の代わりに「!Any(a、b、c)!」の形式で書く価値があります。その後、同じ方法で式「(:abc)|(:xyz)」「!Any( ' abc '、' xyz ')! " また、「|」演算子を取り除くこともできます。 関数のパラメーターとして、たとえば、 「!Any(\ d \ w、 'abc')!」などのPBを使用できます



\ w、\ b、\ dなどの最も単純な式をどうするかを決める必要があります。 一方で、それらは非常にコンパクトですが、たとえば、今では角括弧で使用できるレコードが好きです-[:alnum:]。 便宜上、これらを_alnum_形式のレコードに置き換えることができます。 または、最も単純な\ dと\ wをそのままにしておく必要があります。 テキストに特に表示されない「。」の代わりに、エントリ「_any_」を使用できます。 式自体で無視される同じスペースとタブは、_space_として記述するか、単に引用符で囲むことができます。



必ず通常のif-then-elseステートメントを入力してください。ifの後の式が実行されると、 thenブランチでPBがチェックされ、そうでない場合はelseブランチの後にチェックされます。 その単語省略できると思います。 次に、そのようなRVを作成することができます。



"! 'abc'

if (\w * 3)

{

'xyz'

}

else

{

\d * {1, } 'klmn'

}

!"









ここでは、Cライクな言語のように構文を使用しましたが、これは重要ではありません。 文字通り、この式は次のことを意味します:最初に文字列 'abc'が来て、次にPB '\ w * 3'が実行されたらチェックされ、次に 'xyz'が行かなければなりません。



casewhileforのような演算子を導入する価値さえあります。 さらに、条件で使用する論理演算AND、OR、NOTを入力する必要があります。 「!If( 'abc' && 'xyz')!」という表現があるため、ANDとORについてはわかりません 「!if( 'abcxyz')!」に等しい 、および「!if( 'abc' || 'xyz')!」 - 「!if(any( 'abc'、 'xyz'))!」 。 しかし、否定演算子は、特定の場所にあるべきでないものを正確に決定するために必要です。



PB(_this_)が適用される行自体を格納する変数と同様に、検索が現在実行されている行の位置を示す変数(_pos_変数があるようにします)を入力する必要があります。 次に、演算子「^」をより理解しやすい「!_Pos_ == 0!」に置き換えることができます 、および「$」から「!_pos_ ==(strlen(_this_)-1)!」 たとえば、Pythonとの類推により、行末に別個の表記法を導入する価値があるかもしれません:_pos_ == -1。 これらの同じ変数により、高度で遡及的なチェックが可能になります。



コメントを残す必要があります。 彼らがどのように見えるかはもはや重要ではありません。



割り当て演算子は2つのモードで動作する必要があります。 最初の方法は、正規表現に一致する文字列に変数をチェックして割り当てることです。この場合、 「(?<foo> ...)」のようなレコードが使用されます「!Foo = \ w \ d * ;!」 。 割り当て演算子の終了位置を示すには、セミコロンを使用する必要があります。



2番目の割り当てモードは、正規表現をチェックせずに保存することです。 明確にするために使用されます。たとえば、



"!

foo = !\d\w*!



'abc' foo 'xyz' foo

!"









ここに式があります!\ D \ w *! (感嘆符に注意)は、変数名fooで使用されます。



これらは、RVに関する主要なアイデアです。 このような表現を実際に試してみるのは面白いでしょうが、残念ながら、そのようなパーサーの実装に手を伸ばすことはできません。 一般に、そのような式がPBの古典的な形式に変換され、その後、既製のライブラリによって処理されるという事実から始めることができます。



最後に、URLを見つけるための小さな例を示します。 おそらく、すべてが考慮されているわけではありません。たとえば、ドメインゾーンはcom、net、info、または2文字のみであると考えられています。



"!

unicode = !% any(\d, AF) * 2 ! // Unicode .

// ,

domain = !any ('com', 'net', 'info', (az) * {1, 2})!

host = !any (\w, '_', unicode)!



"http://" (host '.') * {1,} domain '/' * {0, 1}

"!







どこでも間違えられないことを願っていますが、たとえ間違えたとしても怖くはありません。主なことは本質を示すことでした。



結論として、このすべての主な目標は、放射性物質の読みやすさを向上させる方法を思いつくことだったと再度言います。 もちろん、入力されたテキストの量は増えますが、RVが大きい場合は価値があります。



All Articles