2

内部に 2 つの複雑なサブパターンを含む長い正規表現があります。そのサブパターンを任意の順序で一致させるにはどうすればよいですか?

簡単な例:

/(apple)?\s?(banana)?\s?(orange)?\s?(kiwi)?/

そして、私は両方を一致させたい

apple banana orange kiwi
apple orange banana kiwi

これは非常に単純化された例です。私の場合bananaorange長く複雑なサブパターンであり、次のようなことはしたくありません

/(apple)?\s?((banana)?\s?(orange)?|(orange)?\s?(banana)?)\s?(kiwi)?/

文字クラスで char のようなサブパターンをグループ化することは可能ですか?

要求された UPD 実際のデータ:

14:24 26,37 Mb
108.53 01:19:02 06.07
24.39 19:39
46:00

私の弦はずっと長いですが、重要な部分です。ここでは、一致させる必要がある 2 つの行を確認できます。lengthFirst には、(14 分 24 秒) とsize26.37 Mbの 2 つの値があります。2 番目の値には 3 つの値がありますが、順序が異なります: 108.53 Mb 、size01 lengthh 19 m 02 s およびdateJune, 07sizelengthlength

パターンを2回書かないと異なる順序でパターンを一致させる方法がわからないことを除けば、かなり近い正規表現があります。

 (?<size>\d{1,3}\[.,]\d{1,2}\s+(?:Mb)?)?\s?
 (?<length>(?:(?:01:)?\d{1,2}:\d{2}))?\s*
 (?<date>\d{2}\.\d{2}))?

注: これは、既に正常に分岐している大きな正規表現の一部にすぎません。

4

2 に答える 2

2

おそらく、正規表現「&&」の「And」を次のように適応させると役立つでしょう。

use strict;
use warnings;

while(<DATA>){
    print "Matched: $_" if /^(?=.*\bapple\b)(?=.*\bbanana\b)(?=.*\borange\b)(?=.*\bkiwi\b)/
}

__DATA__
apple banana orange kiwi
apple orange banana kiwi
apple orange banana
kiwiorange bananaapple

出力:

Matched: apple banana orange kiwi
Matched: apple orange banana kiwi

これにより、結合の順序が重要でない正規表現で論理ANDが効果的に作成されます。

于 2013-10-27T02:17:50.523 に答える
0

あなたの編集の別の方法:

行に複数の日付、長さ、またはサイズを含めることはできないと想定し、単純な代替を使用します。

$subject = <<<'LOD'
14:24 26,37 Mb
108.53 01:19:02 06.07
24.39 19:39
46:00
LOD;

$pattern = <<<'LOD'
~
^
(?>
    (?> (?<date>   (?> 0[0-9] | 1[012] ) \. (?> [0-2][0-9] | 3[01] )(?! \h+  Mb) ) 
      | (?<length> (?> (?>01:)? [0-9]{1,2} : [0-9]{2} )              )
      | (?<size>   [1-9][0-9]{0,2} [.,] [0-9]?[1-9] (?> \h+  Mb)?    )
    )
    (?> \h | $ )
){1,3} $
~xm
LOD;

preg_match_all($pattern, $subject, $matches, PREG_SET_ORDER);

print_r($matches);

\h: 横書きの白文字 (スペースまたはタブ)

条件付きの方法:

条件付きを使用できます(?(condition)true|false)

(banana)? orange (?(-1)|\g<-1>)

ここ-1で、 はキャプチャ グループ (つまり、最後) の相対位置であり、\g<-1>このキャプチャ グループを参照します。

この条件付きパターンを次のように変換できます。左側の最初のキャプチャ グループが何かをキャプチャした場合、キャプチャ グループに一致するものは他に何もしません。

PHP でのサンプル テキストの例:

$subject = <<<'LOD'
apple banana orange kiwi
apple orange banana kiwi
LOD;

$pattern = '~(apple)?\s?(banana)?\s?(orange)?\s?(?(-2)|\g<-2>)\s?(kiwi)?~';

preg_match_all($pattern, $subject, $matches);

print_r($matches);


知らせ:

鬼車構文を使用すると、サブパターンを簡単に再利用できます\g<...>

\g<2>    # second capturing group of the pattern
\g<-2>   # second capturing group on the left from the current position
\g<+2>   # the same on the right
\g<size> # refer to the subpattern of the named capture (?<size>...)

必要に応じて、定義セクションを使用してパターンを構築できます。次に例を示します。

$pattern = <<<'LOD'
~
# definitions 
(?(DEFINE)
    (?<b> banana )
    (?<o> orange )
    (?<fruit> \g<b> | \g<o> | kiwi | apple )
)

# pattern
\g<b> \s \g<o> | \g<o> \s \g<b>

~x
LOD;

この種のツールを使用すると、サブ パターンの内容を繰り返すことを回避できます。

于 2013-10-27T02:14:35.643 に答える