5

私は正規表現を使用して以下を見つけています:

test:?

次の文字に到達するまで、任意の文字が続きます。

test:?

この正規表現を実行すると、次のようになります。

((?:test:\?)(.*)(?!test:\?))

このテキストについて:

test:?foo2=bar2&baz2=foo2test:?foo=bar&baz=footest:?foo2=bar2&baz2=foo2

私は得ることを期待しました:

test:?foo2=bar2&baz2=foo2

test:?foo=bar&baz=foo

test:?foo2=bar2&baz2=foo2

しかし、代わりにそれはすべてに一致します。正規表現の経験が豊富な人は、私がどこで間違っているか知っていますか?私は以前にパターンマッチングに正規表現を使用しましたが、これは先読み/先読みの私の最初の経験です。

ヘルプ/ヒント/ポインタを事前に感謝します:-)

4

4 に答える 4

4

貪欲なバージョンを探検できると思います。
(拡張)

(test:\? (?: (?!test:\?)[\s\S])* )

于 2012-02-25T01:46:50.017 に答える
2

以下のPerlプログラム

#! /usr/bin/env perl

use strict;
use warnings;

$_ = "test:?foo2=bar2&baz2=foo2test:?foo=bar&baz=footest:?foo2=bar2&baz2=foo2";

while (/(test:\?  .*?) (?= test:\? | $)/gx) {
  print "[$1]\n";
}

質問から目的の出力に加えて、強調用の括弧を生成します。

[テスト:?foo2 = bar2&baz2 = foo2]
[test:?foo = bar&baz = foo]
[テスト:?foo2 = bar2&baz2 = foo2]

正規表現の数量詞は貪欲であり、一致を壊さずにできるだけ多くのことをやりたいと思っていることを忘れないでください。各サブセグメントはできるだけ早く終了します。これは.*?セマンティクスを意味します。

各サブセグメントは、別のサブセグメントtest:?または文字列の終わりのいずれかで終了します。これは、代替手段として(?=...)ゼロ幅の先読みをラップして探します|

上記のコードのパターンは、読みやすさのためにPerlの/x正規表現スイッチを使用しています。使用している言語とライブラリによっては、余分な空白を削除する必要がある場合があります。

于 2012-02-25T01:09:19.247 に答える
0

3つの問題:

  • (?!)否定的な先読みアサーションです。(?=)代わりに、次に来るものがである必要がありますtest:?

  • .*貪欲です。最初のチャンクだけを取得するように、貪欲ではないようにします。

  • 最後のチャンクも必要なので、最後にも一致させたいと思います$

最終結果:

(?:test:\?)(.*?)(?=test:\?|$)

外側のグループも削除しましたが、意味がありません。私が知っているすべてのREエンジンでは、完全一致としてグループ0にアクセスするか、他の方法でアクセスできます(ただし、すべての一致を検索する場合はそうではありません)。必要に応じて元に戻すことができます。

(これはPCREで機能します。私はそれらを使用する習慣がないため、POSIX正規表現で機能するかどうかはわかりません。)

ただし、分割したいだけの場合はtest:?、正規表現は間違ったツールです。そのようなことに対するあなたの言語の作り付けのサポートを使用して文字列を分割します。

Python:

>>> re.findall('(?:test:\?)(.*?)(?=test:\?|$)',
... 'test:?foo2=bar2&baz2=foo2test:?foo=bar&baz=footest:?foo2=bar2&baz2=foo2')
['foo2=bar2&baz2=foo2', 'foo=bar&baz=foo', 'foo2=bar2&baz2=foo2']
于 2012-02-25T00:52:43.970 に答える
-1

((?:test:\?)(.*?)(?=test:\?))正規表現を駆動するために使用している言語を教えていないのに、おそらくあなたは望むでしょう。

文字列全体の.*?一致を妨げることなく、可能な限り少ない文字に.*一致します。可能な限り多くの文字に一致します(貪欲です)。

繰り返しになりますが、これを行うために使用している言語に応じて、おそらく一致させてから文字列を切り刻んでからもう一度一致させるか、言語固有のmatch_allタイプの関数を呼び出す必要があります。

ちなみに、先読みを使用して正規表現を固定する必要はありません(代わりに、パターンを一致させて検索することができます)。したがって、これは(ほとんどの場合)次の場合に実行されます。

test:[?](.*?)test:[?]
于 2012-02-25T00:48:32.620 に答える