7

テストされた文字列の後に任意の数のスペース(ゼロを含む)が続き、その後に。が続かない場合に一致すると予想される(私が信じている)否定的な先読みアサーション があります。<@> *(?!QQQ)<@>QQQ

ただし、テストされた文字列が<@> QQQ正規表現である場合は一致します。

なぜそうなるのかわからないので、この件について助けていただければ幸いです。

これがテストスクリプトです

use warnings;
use strict;

my @strings = ('something <@> QQQ',
               'something <@> RRR',
               'something <@>QQQ' ,
               'something <@>RRR' );


print "$_\n" for map {$_ . " --> " . rep($_) } (@strings);



sub rep {

  my $string = shift;

  $string  =~ s,<@> *(?!QQQ),at w/o ,;
  $string  =~ s,<@> *QQQ,at w/  QQQ,;

  return $string;
}

このプリント

something <@> QQQ --> something at w/o  QQQ
something <@> RRR --> something at w/o RRR
something <@>QQQ --> something at w/  QQQ
something <@>RRR --> something at w/o RRR

そして、私は最初の行がになると思っていましたsomething <@> QQQ --> something at w/ QQQ

4

3 に答える 3

10

「任意の数」にゼロが含まれているため、一致します。したがって、スペースがなく、その後にスペースが続く場合は、「Qが続かない任意の数のスペース」と一致します。

スペースの後の最初のものはそれ自体がスペースではないという別の先読みアサーションを追加する必要があります。これを試してください(テストされていません):

 <@> *(?!QQQ)(?! )

ETA補足:数量詞を+に変更すると、スペースが1つしかない場合にのみ役立ちます。一般的なケースでは、正規表現は常に1つ少ないスペースを取得できるため、成功します。正規表現は一致させたいので、可能な限り後方に曲がってそうします。他のすべての考慮事項(左端、最長など)は後部座席になります。複数の方法に一致する可能性がある場合は、どちらの方法を選択するかを決定します。しかし、一致することは常に一致しないことに勝ちます。

于 2012-04-27T11:53:29.157 に答える
7
$string  =~ s,<@> *(?!QQQ),at w/o ,;
$string  =~ s,<@> *QQQ,at w/  QQQ,;

ここでの問題の1つは、2つの正規表現を別々に表示していることです。最初に、文字列を。なしQQQで置き換え、次に文字列を。で置き換えるように要求しQQQます。これは、ある意味で、実際には同じことを2回チェックしています。例:if (X==0) { ... } elsif (X!=0) { ... }。言い換えれば、コードはより適切に記述されている可能性があります。

unless ($string =~ s,<@> *QQQ,at w/  QQQ,) {
    $string =~ s,<@> *,at w/o,;
}

*数量詞には常に注意する必要があります。0回以上一致するため、空の文字列にも一致する可能性があります。つまり、基本的には、任意の文字列の任意の場所に一致する可能性があります。

ネガティブルックアラウンドアサーションは、一致するために異なるものを1つだけ見つける必要があるという意味で、同様の品質を持っています。この場合、それは+スペースなし+スペース"<@> "としてパーツに一致します。ここで、スペースはもちろん「ではありません」 。数量詞と負の先読みが互いに対抗するため、ここでは多かれ少なかれ論理的な行き詰まりに陥っています。<@>QQQ*

これを解決する正しい方法は、上で示したように正規表現を分離することだと思います。両方の正規表現が実行される可能性を許可する意味はありません。

ただし、理論上の目的では、任意の数のスペース負の先読みの両方を許可する有効な正規表現を固定する必要があります。マークリードが示したように。これが最も簡単かもしれません。

<@>(?! *QQQ)        # Add the spaces to the look-ahead

違いは、スペースとQが互いに固定されているのに対し、以前は別々に一致する可能性があることです。数量詞のポイントを家に持ち帰り、*追加のスペースを削除するという小さな問題を解決するには、次を使用できます。

<@> *(?! *QQQ)

どちらの数量詞も空の文字列と一致する可能性があるため、これは機能します。理論的には、これらを必要な数だけ追加でき、(パフォーマンスを除いて)違いはありません。/ * * * * * * */機能的にはと同等/ */です。ここでの違いは、Qと組み合わせたスペースが存在しない可能性があることです。

于 2012-04-27T14:09:23.473 に答える
4

正規表現エンジンは、一致が見つかるまで、または一致が不可能になるまでバックトラックします。この場合、次の一致が見つかりました。

                         +--------------- Matches "<@>".
                         |   +----------- Matches "" (empty string).
                         |   |       +--- Doesn't match " QQQ".
                         |   |       |
                        --- ----    ---
'something <@> QQQ' =~ /<@> [ ]* (?!QQQ)/x

あなたがする必要があるのは周りのものをシャッフルすることです。交換

/<@>[ ]*(?!QQQ)/

/<@>(?![ ]*QQQ)/

または、正規表現がすべてのスペースにのみ一致するようにすることもできます。

/<@>[ ]*+(?!QQQ)/
/<@>[ ]*(?![ ]|QQQ)/
/<@>[ ]*(?![ ])(?!QQQ)/

PS —スペースは見づらいので、私は[ ]それらをより見やすくするために使用します。とにかく最適化されます。

于 2012-04-27T15:17:01.793 に答える