24

ここで明らかな何かが欠けていると確信していますが、Rに貪欲でない正規表現を使用させることはできません。

> library(stringr)
> str_match('xxx aaaab yyy', "a.*?b")                                         
     [,1]   
[1,] "aaaab"

基本関数は同じように動作します。

> regexpr('a.*?b', 'xxx aaaab yyy')
[1] 5
attr(,"match.length")
[1] 5
attr(,"useBytes")
[1] TRUE

http://stat.ethz.ch/R-manual/R-devel/library/base/html/regex.htmlabの「貪欲な」コメントと同じように一致すると思います。

デフォルトでは、繰り返しは貪欲であるため、可能な最大数の繰り返しが使用されます。これは、? を追加することで「最小」に変更できます。数量詞に。(おおよその一致を可能にする量指定子が他にもあります。TRE のドキュメントを参照してください。)

誰かが私に何が起こっているのか説明してもらえますか?

アップデート。クレイジーなのは、他のいくつかのケースでは、貪欲でないパターンが期待どおりに動作することです。

> str_match('xxx <a href="abc">link</a> yyy <h1>Header</h1>', '<a.*>')
     [,1]                                          
[1,] "<a href=\"abc\">link</a> yyy <h1>Header</h1>"
> str_match('xxx <a href="abc">link</a> yyy <h1>Header</h1>', '<a.*?>')
     [,1]              
[1,] "<a href=\"abc\">"
4

2 に答える 2

9

問題は、2 つの文字列間の最短ウィンドウを一致させることです。@flodel は、正規表現エンジンが文字列を左から右に解析しているため、すべての一致が leftmost であることを正しく述べています。貪欲と怠惰は、右側の境界にのみ適用されます。貪欲な量指定子は、右端の境界までの部分文字列を取得し、怠惰な量指定子は、従うべきサブパターンの最初の出現まで一致します。

を参照してください。

> library(stringr)
> str_extract('xxx aaaab yyy', "a[^ab]*b")
[1] "ab"
> str_extract('xxx aaa xxx aaa zzz', "xxx.*?zzz")
[1] "xxx aaa xxx aaa zzz"
> str_extract('xxx aaa xxx aaa zzz', "xxx(?:(?!xxx|zzz).)*zzz")
[1] "xxx aaa zzz"

1 番目と 3 番目のシナリオは最短のウィンドウを返します。2 番目のシナリオは現在の問題を示していますが、複数文字の入力があります。

シナリオ 1. 境界は 1 文字です

abが 1 文字の場合、否定された文字クラスを使用して最短のウィンドウが検出されます。間にs とsがなくても、次までa[^ab]*bの部分文字列を簡単に取得できます。abab

シナリオ 2. 境界は単一の文字ではない

これらのケースでは、さらに展開できる強化された貪欲なトークンを使用できます。xxx(?:(?!xxx|zzz).)*zzzパターンは に一致し、次に、またはchar シーケンスxxxの開始文字ではない改行文字以外の任意の 0+ 文字(これは、すぐ右側の部分文字列が先読みパターンに一致する場合に一致に失敗する否定的な先読みです)、次に。_xxxzzz(?!xxx|zzz)zzz

これらのマッチングシナリオは、ベース R で簡単に使用できますregmatches(先読みをサポートする PCRE 正規表現フレーバーを使用)。

> x <- 'xxx aaa xxx aaa zzz xxx bbb xxx ccc zzz'
> unlist(regmatches(x, gregexpr("xxx(?:(?!xxx|zzz).)*zzz", x, perl = TRUE)))
[1] "xxx aaa zzz" "xxx ccc zzz"

1 つの注意: ベース R で PCRE 正規表現を使用する場合、またはstr_extract/str_matchでICU 正規表現を使用する場合、.は改行文字と一致しません。その動作を有効にするに(?s)は、パターンの先頭 (インライン DOTALL 修飾子) に追加する必要があります。

于 2016-11-11T21:24:35.753 に答える