77

私のホームディレクトリには、Drupalプラットフォームを含むdrupal-6.14フォルダーがあります。

このディレクトリから、次のコマンドを使用します。

find drupal-6.14 -type f -iname '*' | grep -P 'drupal-6.14/(?!sites(?!/all|/default)).*' | xargs tar -czf drupal-6.14.tar.gz

このコマンドは、drupal-6.14フォルダーをgzipします。ただし、sites/allとsites/defaultを除くdrupal-6.14/sites/ のすべてのサブフォルダーは除外されます。

私の質問は正規表現についてです:

grep -P 'drupal-6.14/(?!sites(?!/all|/default)).*'

この式、除外したいすべてのフォルダーを除外するように機能しますが、その理由はよくわかりません。

正規表現を使用して

サブパターンxを含まない文字列を除くすべての文字列に一致します。つまり、サブパターンを否定します。

私は、これらの問題を解決するための一般的な戦略はネガティブな先読みの使用であることを理解していますが、ポジティブおよびネガティブな先読み(前/後ろ)がどのように機能するかを満足のいくレベルまで理解したことはありません。

何年にもわたって、私はそれらの多くのウェブサイトを読みました。PHPとPythonの正規表現のマニュアル、http://www.regular-expressions.info/lookaround.htmlなどの他のページなどですが、私はそれらを完全に理解したことはありません。

誰かがこれがどのように機能しているかを説明し、おそらく同様のことを行ういくつかの同様の例を提供できますか?

--アップデート1:

Andomarの応答について:二重否定の先読みは、単一の正の先読みステートメントとしてより簡潔に表現できますか。

すなわち:

'drupal-6.14/(?!sites(?!/all|/default)).*'

に相当:

'drupal-6.14/(?=sites(?:/all|/default)).*'

???

--アップデート2:

@andomarと@alanmooreによると、二重否定の先読みを正の先読みと交換することはできません。

4

3 に答える 3

144

否定的な先読みは、この位置では、次の正規表現は一致できないことを示しています。

簡単な例を見てみましょう。

a(?!b(?!c))

a      Match: (?!b) succeeds
ac     Match: (?!b) succeeds
ab     No match: (?!b(?!c)) fails
abe    No match: (?!b(?!c)) fails
abc    Match: (?!b(?!c)) succeeds

最後の例は二重否定です。これにより、その後に。がb続きcます。ネストされた負の先読みは正の先読みになりcます。存在する必要があります。

各例では、のみaが一致します。先読みは単なる条件であり、一致したテキストには追加されません。

于 2009-11-17T16:13:56.650 に答える
14

ルックアラウンドはネストできます。

したがって、この正規表現は、「/all」または「/default」が後に続かない sites」が後に続く「drupal-6.14/」と一致します。

紛らわしい?別の言葉を使用すると、「drupal-6.14 /」に一致し、その後に「/all」または「/default」が続く場合を除き、 「sites」が続かないと言えます。

于 2009-11-17T15:06:35.007 に答える
6

このように正規表現を修正する場合:

drupal-6.14/(?=sites(?!/all|/default)).*
             ^^

drupal-6.14/...次に、またはが後に続くsites、または以外の何か を含むすべての入力に一致します。例えば:/all/default

drupal-6.14/sites/foo
drupal-6.14/sites/bar
drupal-6.14/sitesfoo42
drupal-6.14/sitesall

元の正規表現に一致するように変更?=する?!と、それらの一致が無効になります。

drupal-6.14/(?!sites(?!/all|/default)).*
             ^^

つまり、これは単に、またはの後に他の何かを続けることができないことを意味しdrupal-6.14/ます。したがって、これらの入力は正規表現を満たします。sites /all/default

drupal-6.14/sites/all
drupal-6.14/sites/default
drupal-6.14/sites/all42

しかし、他の回答(およびおそらくあなたの質問)のいくつかから明らかではないかもしれないことは、あなたの正規表現が他の入力を許可し、drupal-6.14/その後に他のものが続くということsitesです。例えば:

drupal-6.14/foo
drupal-6.14/xsites

結論:つまり、正規表現は基本的に、名前がまたは以外で始まるサブディレクトリを除く、のすべてのサブディレクトリを含めるように言っています。drupal-6.14 sitesalldefault

于 2016-05-10T20:41:21.843 に答える