如何使用正则表达式找到命令?

我有一些图像命名与生成uuid1字符串。例如81397018-b84a-11e0-9d2a-001b77dc0bed.jpg。我想用“find”命令找到所有这些图像:

find . -regex "[a-f0-9\-]\{36\}\.jpg".

但这并不奏效。正则表达式有问题吗?有人能帮我一下吗?

572820 次浏览

尝试使用单引号(')来避免字符串的shell转义。记住,表达式需要匹配整个路径,即需要看起来像:

 find . -regex '\./[a-f0-9-]*.jpg'

除此之外,我的find (GNU 4.4.2)似乎只知道基本的正则表达式,尤其是{36}语法。我想你只能将就着不戴了。

-regex查找表达式匹配完整的名字,包括当前目录的相对路径。对于find .,它总是以./开始,然后是任何目录。

此外,这些是emacs正则表达式,它们有其他的转义规则,而不是通常的egrep正则表达式。

如果这些都直接在当前目录中,那么

find . -regex '\./[a-f0-9\-]\{36\}\.jpg'

应该工作。(我不是很确定——我不能让计数重复在这里工作。)你可以通过-regextype posix-egrep切换到egrep表达式:

find . -regextype posix-egrep -regex '\./[a-f0-9\-]{36}\.jpg'

(请注意,这里所说的一切都是GNU的,我不知道BSD的任何东西,这也是Mac的默认设置。)

find . -regextype sed -regex ".*/[a-f0-9\-]\{36\}\.jpg"

注意,你需要在开始时指定.*/,因为find匹配整个路径。

例子:

susam@nifty:~/so$ find . -name "*.jpg"
./foo-111.jpg
./test/81397018-b84a-11e0-9d2a-001b77dc0bed.jpg
./81397018-b84a-11e0-9d2a-001b77dc0bed.jpg
susam@nifty:~/so$
susam@nifty:~/so$ find . -regextype sed -regex ".*/[a-f0-9\-]\{36\}\.jpg"
./test/81397018-b84a-11e0-9d2a-001b77dc0bed.jpg
./81397018-b84a-11e0-9d2a-001b77dc0bed.jpg

我的版本:

$ find --version
find (GNU findutils) 4.4.2
Copyright (C) 2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.


Written by Eric B. Decker, James Youngman, and Kevin Dalley.
Built using GNU gnulib version e5573b1bad88bfabcda181b9e0125fb0c52b7d3b
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION FTS() CBO(level=0)
susam@nifty:~/so$
susam@nifty:~/so$ find . -regextype foo -regex ".*/[a-f0-9\-]\{36\}\.jpg"
find: Unknown regular expression type `foo'; valid types are `findutils-default', `awk', `egrep', `ed', `emacs', `gnu-awk', `grep', `posix-awk', `posix-basic', `posix-egrep', `posix-extended', `posix-minimal-basic', `sed'.

从其他答案来看,这似乎是find的错。

但是你可以这样做:

find . * | grep -P "[a-f0-9\-]{36}\.jpg"

您可能需要稍微调整grep,并根据需要使用不同的选项,但它是有效的。

当使用正则表达式查找指令时,应该使用绝对目录路径。 在您的示例中,

. xml
find . -regex "[a-f0-9\-]\{36\}\.jpg"

应该改为

find . -regex "./[a-f0-9\-]\{36\}\.jpg"

在大多数Linux系统中,正则表达式中的某些规则不能被该系统识别,因此必须显式地指出-regexty like

find . -regextype posix-extended -regex "[a-f0-9\-]\{36\}\.jpg"

简单的方法-你可以在开头指定.*,因为find匹配整个路径。

$ find . -regextype egrep -regex '.*[a-f0-9\-]{36}\.jpg$'

找到的版本

$ find --version
find (GNU findutils) 4.6.0
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
<http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.


Written by Eric B. Decker, James Youngman, and Kevin Dalley.
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION
FTS(FTS_CWDFD) CBO(level=2)

在Mac OS X上(BSD查找):与公认的答案效果相同。

$ find -E . -regex ".*/[a-f0-9\-]{36}.jpg"

man find表示-E使用扩展的正则表达式支持

注意:需要.*/前缀来匹配一个完整的路径:

为了便于比较,下面是GNU/Linux版本:

$ find . -regextype sed -regex ".*/[a-f0-9\-]\{36\}\.jpg"

如果你想保持跨平台兼容性,我找不到内置的正则表达式搜索选项,可以在不同版本的find中以一致的方式工作。

与grep结合

  1. 正如@yarian所建议的,你可以运行一个包含过度的查找,然后通过grep运行输出:

find . | grep -E '<POSIX regex>'

这可能很慢,但如果你需要使用完整的正则表达式,并且不能将你的搜索重新格式化为一团,它将为你提供跨平台的正则表达式搜索

重写为一个glob

  1. -name选项与globb兼容,后者将提供有限的(但跨平台的)模式匹配。

你可以在命令行中使用所有的模式,比如* ? {} **。尽管没有完整的regex那么强大,但您可能能够根据您的用例将搜索重新制定为glob。

网上搜索 -许多详细介绍完整功能的教程都可以在网上找到

有一件事我没有看到涉及的是如何结合正则表达式和正则查找语法。

例如:我想在BSD / Linux上找到核心转储文件,我改变到我想扫描的根目录。cd /然后执行:

find \( -path "./dev" -o -path "./sys" -o -path "./proc" \) -prune -o -type f -regextype sed -regex ".*\.core$" -exec du -h {} \; 2> /dev/null

因此,我使用prune命令来排除多个系统目录,然后对剩余的文件进行正则表达式。删除任何错误输出(stderr)。

重要的部分是首先使用Find语法,然后对正则表达式使用OR (-o)。