findコマンドパターンマッチングにおけるsedとgrepの使い方の違い

findコマンドパターンマッチングにおけるsedとgrepの使い方の違い

sed以下の例が利用できない理由を理解しようとしています。

すべてのフォルダにというフォルダを含む入れ子になったフォルダ構造がありますPKGBUILD。たとえば、特定のパターンを含むファイルの相対パスを印刷したいとします。pkgname=.*dbus

findと一緒に使用すると、grep期待される結果が得られます。

find . -name 'PKGBUILD' -exec grep -q 'pkgname=.*dbus' {} \; -print

私は正しく得る

./packages/dbus-python/repos/extra-x86_64/PKGBUILD
./packages/dbus-python/trunk/PKGBUILD
./packages/dbus-glib/repos/extra-x86_64/PKGBUILD
./packages/dbus-glib/trunk/PKGBUILD

PKGBUILDそのファイルには正しいパターンが含まれているため、相対ファイルパスに出力されます。私が理解しているように、-qgrepのオプションは一致するものがない限り印刷を無視します。

ただし、を使用して同じ動作をシミュレートできる必要がありますsed。私は次のように使用します

find . -name 'PKGBUILD' -exec sed -n '/pkgname.*dbus/q' {} \; -print

whereは出力を省略し、一致するものが見つかったらすぐに終了する-nために使用されます。qただし、コマンドは以下を出力します。すべて PKGBUILD一致するかどうかに関係なく、ツリー内のファイルですsedgrepここで動作が異なる理由は何であり、sedこのコマンドを機能させるにはどうすればよいですかsed

答え1

すべてのコメント作成者がすでに述べたように、sedviaパターンの一致またはvia間の戻り状態の間にはかなりの違いがありますgrep

一方、見つかった一致grep -qのみが返される状態は、一致が見つかったかどうかに関係なく常に返されます(場合によってはファイルやストリームを読み取ることができず、実際には提供されません)。 GNU拡張機能を使用すると、この戻り状態を変更できます。つまり、パターン一致が発生した場合にのみ返されるように変更できます。0sed00sedsed1

sed -n '/pkgname.*dbus/q1'

ただし、このfindプログラムは前のジョブの戻り状態printにのみ依存します。つまり、次を使用して戻り状態を無効にする必要があります。0execsed!

findthenを使用する完全なコマンドsedは次のとおりです。

find . -name 'PKGBUILD' ! -exec sed -n '/pkgname.*dbus/q1' {} \; -print

出力を含む

./packages/dbus-python/repos/extra-x86_64/PKGBUILD
./packages/dbus-python/trunk/PKGBUILD
./packages/dbus-glib/repos/extra-x86_64/PKGBUILD
./packages/dbus-glib/trunk/PKGBUILD

予想通り。素晴らしい洞察を提供してくれた@Paul_Pedant、@steeldriver、特に@don_crisstiに感謝します!

関連情報