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文件包含正确的模式。据我了解,-q只要没有找到匹配项,grep 中的选项就负责忽略打印。

但是我应该能够通过使用来模拟相同的行为sed。我按以下方式使用它

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

where-n用于省略输出并q在找到匹配项时立即退出。但是,该命令输出每一个 PKGBUILD树中的文件,无论是否sed匹配任何内容。为什么grep和这里的行为sed如此不同,我将如何使该sed命令起作用?

答案1

正如所有评论者已经提到的那样,模式匹配 viased或 via之间的返回状态之间存在显着差异grep

grep -q仅返回0找到的匹配项的状态sed总是返回,0无论是否找到匹配项(在某些情况下,文件或流无法读取,并且实际上没有给出0)。通过sedGNU 扩展,可以修改此返回状态,即我们可以更改它,以便sed1在发生模式匹配时返回。

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

然而,该find程序仅print依赖于0前一个exec操作的返回状态,即我们需要sed使用 来否定返回状态!

find使用then 的完整命令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 的深刻见解!

相关内容