2

Ruby 1.9.3環境でどのよう.{n}?<option>:動作するかを理解しようとしていました。Regexpしかし、以下のコードがどのように出力を生成するか理解できませんでした:

irb(main):001:0> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.{2}(?m:.)\Z/
=> ["fin\n", "fin\r\n", "find"]
irb(main):002:0> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.{1}(?m:.)\Z/
=> ["fin\n", "fi\n\n"]
irb(main):003:0> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.{1}(?m:.)\Z/
=> []
irb(main):010:0> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.(?m:.)\Z/
=> ["fin\n", "fi\n\n"]
irb(main):011:0> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.(m:.)\Z/
=> []
irb(main):012:0> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.(?m:.)\z/
=> []

IRB上記のコードがターミナルで上記の出力を生成するためにどのように機能したかを理解するのを手伝ってくれる人はいますか?

ありがとう、


@Kevin の最後の段落に従って、以下を試してみたところ、期待される望ましい出力が見つかりました。

irb(main):014:0> %W{fin fi\n\n \n\n fin\r\n find}.grep /f.(?m:.)\z/
=> ["fin"]
irb(main):015:0> %W{fin fi\n\n \n\n fin\r find}.grep /f.(?m:.)\z/
=> ["fin"]
irb(main):016:0> %W{fin fi\n \n\n fin\r\n find}.grep /f.(?m:.)\z/
=> ["fin", "fi\n"]
irb(main):017:0> %W{fin fi\n \n\n fr\n find}.grep /f.(?m:.)\z/
=> ["fin", "fi\n", "fr\n"]
irb(main):018:0>

どうもありがとう@ケビン。あなたは私が概念全体を理解するのを助けました!

4

1 に答える 1

3

{n}「前の原子n時間を繰り返す」ことを意味します。正規表現では、アトムは自己完結型の単位です。したがって、単一の文字はアトムです。ドットも同様です。グループは、文字クラスと同様に (他のアトムを含む) アトムでもあります。So.{n}は「n文字に一致」を意味します (「任意の文字に一致」を意味するため.)。

{n}は、繰り返しのたびに同じテキストに一致する必要がないという点で、後方参照とは異なります。.{5}のように動作し.....ます。

この構成もより強力です。2 つの数値を取ることができ、その範囲全体の繰り返し回数に一致します。つまり.{3,5}、「3 ~ 5 文字を一致させる」という意味です。and.{3,}は「3 文字以上一致」を意味します。必要に応じて、、、およびに?置き換えることができます。{0,1}*{0,}+{1,}


?<option:実際のものではありません。です。これにより、 にリストされて(?<option>:<pattern>)いるすべてのフラグが オンになります。これはグループに似ていますが、実際には後方参照を作成しません。つまり、この式は「フラグがオンになっているように 1 文字に一致する」という意味です。nhahtdh がコメントで述べたように「\n に一致」の動作を考えると、この式は「改行以外の任意の文字に一致し、その後に任意の文字が続き、その後に改行以外の任意の文字が続く」ことを意味します。<option><pattern>(?m:.)mm.(?m:.).

この構成には 2 つの利点があります。まず、パターンの一部にのみフラグを適用することができます。これは、場合によっては便利です。次に、パターン全体をこの構文でラップすると、正規表現がどこで使用されているかに関係なく、正規表現に適用されるフラグを制御できます。これは、正規表現をユーザーとして提供していて、プログラムのソースを制御できない場合に便利です。


あなたが与えた例を見てみましょう:

> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.{2}(?m:.)\Z/
=> ["fin\n", "fin\r\n", "find"]

あなたのパターン/f.{2}(?m:.)\Z/は、「fに一致し、その後に2つの任意の文字(ただし改行)が続き、その後に任意の文字が続き、文字列の末尾または改行の直前にアンカーする」ことを意味します。

したがって、3 つの一致のそれぞれで、 にfin一致しf.{2}ます。1番目、2 番目、 3 番目に(?m:.)一致します。Andは、最初の文字列の末尾、2 番目の改行の直前、3 番目の文字列の末尾に一致します。\n\rd\Z

fi\n\n最初のhere は、フラグなしのfrom\nと一致できないため、一致しません。..{2}m

> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.{1}(?m:.)\Z/
=> ["fin\n", "fi\n\n"]

ここでは両方の場合にfi一致します。と に一致し、どちらの場合も改行の前に一致します。f.{1}(?m:.)n\n\Z

fin\r\n\ZCRLFペアの前ではなく、文字列の最後の改行の前にのみ一致するため、一致しません。に一致するものがないため、 andfindは一致しませんd

> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.{1}(?m:.)\Z/
=> []

ここにコピー&ペーストのエラーがあると思います。これは前のパターンと同じで、そのように一致します。

> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.(?m:.)\Z/
=> ["fin\n", "fi\n\n"]

これも前回のパターンと同じです。..{1}同じものです。実際、{1}何も変更せずに正規表現からいつでも取り除くことができます。

> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.(m:.)\Z/
=> []

このパターンで を削除する?と、 の意味が変わり(m:.)ます。これにより、オプションが変更されなくなりました。これは pattern に一致するキャプチャ グループにすぎm:.ませんが、これはもちろん入力では発生しません。

> %W{fin\n fi\n\n \n\n fin\r\n find}.grep /f.(?m:.)\z/
=> []

あなたはここに変わり\Zまし\zた。これら 2 つの違いは\Z、末尾の改行の前で一致する可能性があります\zが、文字列の末尾でのみ一致する必要があります。末尾の改行の前で一致できなければ、ここでの入力はどれも一致しません。ただし、たとえば、fin(改行なし) またはfi\n(2 番目の改行なし) がある場合は機能します。

于 2013-01-17T18:40:07.203 に答える