Contents

Linux查找带有正则表达式的命令

1. 简介

在本教程中,我们将讨论命令find 与正则表达式 (regex) 的使用。我们将看看如何指定正则表达式以进一步细化搜索结果。

2. 正则表达式入门

在展示如何在find中使用正则表达式之前,让我们先了解一下它们是什么以及它们是如何构造的。

**正则表达式 (简称 regex)**是由指定搜索模式的字符序列描述的强大工具。**这就是为什么它们与find一起使用产生更精确的搜索和更精简的命令。

有不同类型的正则表达式和格式。下面解释的概念在它们之间是一致的。但是,更高级的功能需要知道正在使用哪种正则表达式类型,因为它们之间存在差异。find命令可接受的正则表达式风格将在下一节中详细介绍。

2.1. 主要的正则表达式标记和示例

尽管有时被认为令人生畏,但正则表达式改进了搜索并增强了与命令行的交互。仅凭基本知识,我们就可以从中获利。

作为一个快速介绍,有匹配多个字符的正则表达式标记

  • 句点(.):匹配任何字符一次(换行符除外):qe将匹配字符串qweqreqee但不匹配字符串qeqwwe
  • 星号 ( * ):它匹配零次或多次出现的前面字符/正则表达式:qw*e 将匹配字符串qeqweqwwe但不匹配字符串qre
  • 反斜杠 ( \ ):转义特殊字符,例如,搜索句点:q.e 将匹配字符串qe,但不匹配字符串qreqeeqeqwwe
  • 方括号 ( [string] ):方括号内的字符串的任何字符都返回正匹配:q[we]r 将匹配字符串 qwrqer但不匹配字符串qr、qwerqwewer
  • 插入符号 ( ^ ):它否定方括号内的内容(尽管它也指定在文件中搜索时的行首):  q[^we]r将匹配字符串qarqsr但不匹配字符串qwrqer

经常结合使用的两个标记是 .*,根据前面的讨论,它将匹配除换行符之外的任何字符的零次或多次出现,这意味着它将匹配任何字符串!

3. 命令说明

find 命令的使用可以分为两个部分:path和搜索expression

find [path] [expression]

** path是搜索的目录。expression部分还包括在符合搜索条件的文件中可能采取的操作。**在那里,命令find 具有与正则表达式相关的三个选项。我们现在向他们展示一些用例示例。以下模型目录将用于示例:

$ tree ./
./
├── a0
├── a0.sh
├── A0.sh
├── a1
├── a1.sh
├── A1.sh
├── a2
├── ca
├── cb
├── cc
└── folder
    ├── a0
    ├── a1
    └── a0folder
        ├── a0
        └── a1
2 directories, 13 files

3.1. 使用*-regex*

第一个选项是*-regex*和正则表达式:

find [path] -regex [regular_expression]

使用此命令,搜索path,并返回符合正则表达式的文件regular_expression模式包括完整的文件名,包括根路径目录。**这意味着如果在当前目录中查找,regular_expression应该以 ./ 开头(使用反斜杠转义特殊字符)。

以下命令查找当前目录 ( ./ ) 中的文件(带有*-type f标志),这些文件以字母a开头,后跟01*:

$ find ./ -type f -regex '\.\/a[01].*'
./a1
./a0
./a1.sh
./a0.sh

文件a2未返回,因为字母a后面没有01。我们也可以使用以下命令在一级目录而不是当前目录中搜索:

$ find ./ -type f -regex '\.\/[^/]*\/a[01][^/]*'
./folder/a1
./folder/a0

最后两个正则表达式之间存在两个差异。首先,标记 [^/]*/ 指的是任何不包含任何斜杠 ( [^/]* ) 后紧跟以字母a开头的文件名之前的斜杠 ( / ) 的字符串。其次,我们将句点替换为 [^/] 以表示在字母a之后不能再出现斜杠。

子目录中的文件不符合正则表达式:在第一个斜杠(当前目录)和紧跟字母a的斜杠之间,子目录有额外的斜杠(例如 ./folder/a0folder/a0)。

最后,要包含所有子目录中的所有文件,我们可以使用:

$ find ./ -type f -regex '.*a[01].*'
./folder/a0folder
./folder/a0folder/a0
./folder/a0folder/a1
./folder/a0
./folder/a1
./a0
./a1
./a0.sh
./a1.sh

3.2. 使用*-iregex*

第二个选项是*-iregex*:

find [path] -iregex [regular_expression]

该命令执行与使用*-regex选项相同的搜索,但忽略搜索模式的字母大小写。作为助记规则,命令-iregex*代表不区分大小写的正则表达式。

如果我们修改之前的命令之一以仅查找带点的文件(通过包含*[.]*),则输出如下所示:

$ find ./ -type f -regex '\.\/a[01][.].*'
./a0.sh
./a1.sh

使用*-iregex标志而不是-regex标志的结果也包括带有大写字母A*的文件:

$ find ./ -type f -iregex '\.\/a[01][.].*'
./a0.sh
./A1.sh
./A0.sh
./a1.sh

3.3. 使用*-regextype*

最后,选项*-regextype*选择正则表达式的类型:

find [path] -regex [regular_expression] -regextype [regex_type]

不同的正则表达式类型可用于命令find

  • findutils
  • emacs(除非另有说明,这是默认选项)
  • gnu-awk
  • grep
  • egrep
  • posix-awk
  • posix-basic
  • posix-egrep
  • posix-extended

之前定义的标记与所有这些类型的正则表达式兼容。但是,更高级的搜索查询可能会在不同的正则表达式类型下产生不同的结果。有一个全面的GNU 网页 专门用于详细说明不同的语法。

4. 与 Bash Globbing 的比较

在使用 Linux 一点点之后,bash globbing 肯定出现在ls之类的命令中。让我们考虑以下命令:

ls *.png

它列出了格式扩展名为*.png*的所有文件。同时,命令:

ls M*.png

列出所有具有*.png格式扩展名并以字母 M 开头的文件。这是 bash globbing 的作用:文件名完成。使用find*命令搜索名称时使用 Bash 通配符。

即使它们看起来相似,bash globbing 和正则表达式也呈现出不同的语法——使事情变得复杂。我们讨论两个最相关的差异。句点 (.) 表示 bash 通配符中的文字句点,但表示正则表达式中的任何单个字符。第一个命令显示了 bash 通配方法:

$ find ./ -type f -name 'a*.sh'
./a0.sh
./a1.sh

为了获得相同的结果,我们可以使用以下正则表达式查找命令:

$ find ./ -type f -regex '\.\/a.*\.sh'
./a0.sh
./a1.sh

bash globbing 和正则表达式之间的另一个区别是星号 ( * ):它表示 bash globbing 中的任何字符的零个或多个,但在正则表达式中,它表示前面的字符的零个或多个。因此,无论是扩展 bash 通配符还是正则表达式,类似命令的行为都不同。当我们使用 bash globbing 时,以下命令会返回所有以c开头的文件:

$ find ./ -type f -name 'c*'
./cb
./cc
./ca

但是,如果类似的搜索模式具有正则表达式,它会返回名称仅包含c的所有文件:

$ find ./ -type f -regex '\.\/c*'
./cc

在目录中搜索以使用 bash 通配符或正则表达式时,我们应该牢记这些差异。