【问题标题】:find command can't exclude the exact regexfind 命令不能排除确切的正则表达式
【发布时间】:2020-11-03 19:21:01
【问题描述】:

我有以下脚本:

#!/bin/bash
arg=$1
exclude='(/etc/alternatives/(awk|vim)|/usr/sbin/poweroff)$'
find $arg -type f,l,c,b -regextype posix-extended -not -regex "${exclude}" -print

我没有在每个文件的开头使用^,所以它可以从任何东西开始。但是我在每个文件的末尾都使用了$

所以当我以这种方式运行脚本时,它可以正常工作:

$ sudo bash script.sh /etc/ | grep awk
/etc/alternatives/nawk
/etc/alternatives/nawk.1.gz
/etc/alternatives/awk.1.gz

但是当我这样做的时候是错误的:

$ sudo cp -rv /etc/ /tmp/
$ sudo bash script.sh /tmp/etc/ | grep awk
/tmp/etc/alternatives/awk
/tmp/etc/alternatives/nawk
/tmp/etc/alternatives/nawk.1.gz
/tmp/etc/alternatives/awk.1.gz

在这里您看到文件 /tmp/etc/alternatives/awk,由于缺少 ^ 符号,因此不应在结果中传递。

更新

这个模式很好用,但我想使用上面的一个:

find $arg -type f,l,c,b | grep -Ev "${exclude}"

【问题讨论】:

  • 尝试将 -regextype 从 postix-extended 更改为 posix-egrep

标签: regex linux bash find


【解决方案1】:

据我所知,-regex 测试是特定于 GNU 的 find 实现的功能;它不是由 POSIX 定义的。无论如何,几乎可以肯定 GNU 的实现是您会在您最喜欢的 Linux 发行版上找到的那个。 Its manual 有话要说:

测试:-regex expr
测试:-iregex expr
如果整个文件为真 name 匹配正则表达式 expr。 这是一场比赛 路径,而不是搜索。 [...]

(强调添加)。也就是说,测试总是像正则表达式被锚定到行的开始端一样执行,即使模式中没有明确的锚点。您可以通过使用 .* 为您的正则表达式添加前缀和/或后缀来解决此问题。

对于您的示例,可能如下所示:

exclude='.*(/etc/alternatives/(awk|vim)|/usr/sbin/poweroff)'

我省略了不需要的尾随锚点,因为这对我来说似乎更清楚,但如果您更愿意保留它,那就这样做吧——它没有害处。

【讨论】:

  • 谢谢。这是工作。哪种方法更好? grep -Ev "${exclude}" -regextype posix-extended -not -regex "${exclude}" -print?
  • @M.J, rhe grep 版本更便携,但如果您只关心支持具有 GNU find 的系统,那么通过 -regex 使用一个进程完成这项工作会更轻量级,而不是使用双进程管道。
  • 但是当您的脚本位于/tmp 并且您想以这种方式运行脚本时:bash script.sh etc/ 它不起作用,您必须始终使用绝对路径作为参数。
  • @M.J,find 与正则表达式匹配的路径与它最终打印的路径相同。这些以指定给它的起始点目录名称开头。我认为这个问题是关于(GNU)find-regex 测试的语义,这就是我所回答的。我的建议可以解决问题中提供的示例。如果您需要帮助调整正则表达式以服务更多案例,那么这将是另一个问题的主题。
  • 所以我们需要使用realpath命令来获取文件的绝对路径来处理它。谢谢。
猜你喜欢
  • 2015-08-27
  • 1970-01-01
  • 1970-01-01
  • 2011-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-20
  • 1970-01-01
相关资源
最近更新 更多