私のホームディレクトリには、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し、drupal-6.14/sites /のすべてのサブフォルダーを除くsites/allおよびsites/defaultを除きます。これには含まれます。
私の質問は正規表現にあります:
grep -P 'drupal-6.14/(?!sites(?!/all|/default)).*'
式worksは、除外したいすべてのフォルダーを除外しますが、その理由はよくわかりません。
これは、正規表現を使用した一般的なタスクです
do n'tにサブパターンxが含まれる文字列を除く、すべての文字列に一致します。または、言い換えると、サブパターンを無効にします。
私は(これらの問題を解決する一般的な戦略はネガティブな先読みの使用であることを理解していますが、ポジティブとネガティブな先読みがどのように機能するかを満足できるレベルまで理解したことはありません。
長年にわたり、私はそれらに関する多くのウェブサイトを読みました。 PHP and Python正規表現マニュアル、 http://www.regular-expressions.info/lookaround.html のような他のページ等々、しかし、私は決して本当にはそれらをしっかりと理解していませんでした。
誰かが、これがどのように機能しているかを説明し、おそらく同様のことをするいくつかの同様の例を提供できますか?
-アップデート1:
Andomarの応答について:二重の負の先読みは、単一の正の先読みステートメントとしてより簡潔に表現できますか?
つまり:
'drupal-6.14/(?!sites(?!/all|/default)).*'
に相当:
'drupal-6.14/(?=sites(?:/all|/default)).*'
???
-更新2:
@andomarと@alan mooreによると、二重の負の先読みを正の先読みと交換することはできません。
負の先読みは、この位置では、次の正規表現は一致しないと言います。
簡単な例を見てみましょう。
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
最後の例はdouble negationです:b
の後にc
が続くことを許可します。ネストされた負の先読みは、正の先読みになります。c
が存在する必要があります。
各例では、a
のみが一致します。先読みは単なる条件であり、一致したテキストには追加されません。
ルックアラウンドはネストできます。
したがって、この正規表現は、「drupal-6.14 /」、つまりnotの後に「sites」、つまりnotの後に「/ all」または「/ default」が一致します。
紛らわしい?別の単語を使用すると、「drupal-6.14 /」に一致すると言うことができます。これは、notに「sites」が続くnlessに「/ all」または「/」が続くデフォルト"
このように正規表現を修正する場合:
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/
が/not の後にsites
の後に //all
または/default
以外のものが続くことを意味します。したがって、 these 入力は正規表現を満たします。
drupal-6.14/sites/all
drupal-6.14/sites/default
drupal-6.14/sites/all42
しかし、他のいくつかの答え(そしておそらくあなたの質問)から明らかでないかもしれないのは、あなたの正規表現がdrupal-6.14/
の後にsites
以外のものも続く other 入力も許可することです。例えば:
drupal-6.14/foo
drupal-6.14/xsites
結論:つまり、正規表現は基本的に all drupal-6.14
のサブディレクトリ except 名前のsites
のサブディレクトリを含めるように言っていますall
またはdefault
以外のもので始まります。