Grep:如何添加“或”条件?

Har*_*arv 55 grep

如何将条件 OR 引入 grep?例如,为(JPEG 或 JPG)搜索文件类型,然后仅将这些文件发送到照片文件夹中。例如。我知道如何将文件发送到我想要的位置,并获取文件类型,我只需要 grep 部分的一些帮助。

我在 OS X 上,IMO 似乎已经修改/定制了 *nix 实用程序,而不是我在 *nix 环境中习惯的。所以希望答案可以尽可能通用/便携。

jfg*_*956 72

如果你想在grep中引入一个OR,用REGEXP引入它是错误的方式。尝试使用-egrep 选项:

grep -e PATTERN1 -e PATTERN2 your_file
Run Code Online (Sandbox Code Playgroud)

将匹配带有 PATTERN1 或 PATTERN2 的行。

  • `grep -E "ATTN|MASS|BOND|ANGLE|DIHE|IMPROPER" temp.dat` 和 `grep -e ATTN -e MASS -e BOND -e ANGLE -e DIHE -e IMPROPER temp.dat` 相同。 (15认同)

小智 55

这是另一种方法:

grep "foo\|bar" /path/to/file
Run Code Online (Sandbox Code Playgroud)

这可以找到文本foobarfile

  • 谢谢你!其他答案很有趣,但这就是我一直在寻找的答案——反斜杠。谢谢。 (4认同)
  • 是的,我总是忘记**反斜杠管道**..而且你的解决方案比我的`cat /path/to/file | 短得多。grep "foo\|bar"`. 我一定要记住你的做法!;) (4认同)

Gun*_*sen 41

我对正则表达式也很陌生,但由于没有其他人回答我会试一试。管道运算符“|” 用于 OR 运算符。

下面的正则表达式应该让你去某个地方。

.+((JPG)$|(JPEG)$)
Run Code Online (Sandbox Code Playgroud)

(匹配任何一次或多次,最后是“JPG”或“JPEG”)

扩展答案(在了解了 (e)grep 后进行了编辑):假设您有一个文件夹,其中包含以下文件:

test.jpeg, test.JpEg, test.JPEG, test.jpg, test.JPG, test.notimagefile, test.gif
Run Code Online (Sandbox Code Playgroud)

(名字没那么有创意……)

首先,我们首先定义我们对模式的了解:我们知道我们正在寻找名称的结尾。因此,我们使用“$”操作数来定义每一行必须以定义的模式结束。我们知道模式必须是 JPEG 或 JPG。为此,我们使用管道“|” 作为或操作数。我们的模式现在是:

((JPEG)|(JPG))$
Run Code Online (Sandbox Code Playgroud)

(匹配任何以“JPEG”或“JPG”结尾的行)

但是我们看到在这个例子中,唯一的区别是可选的“E”。为此,我们可以使用“?” 操作数(意味着可选)。我们写:

(JP(E)?G)$
Run Code Online (Sandbox Code Playgroud)

(Mach 任何以模式结尾的文件,例如:“J”,后跟“P”,后跟可选的“E”,后跟“G”)。

但是,我们可能还想匹配文件名中带有小写字母的文件。为此,我们引入了字符类“[...]”。意思匹配以下任一。我们写:

([jJ][pP]([eE])?[gG])$
Run Code Online (Sandbox Code Playgroud)

(匹配任何以 at 模式结尾的文件,例如:“j”或“J”,后跟“p”或“P”,后跟可选的“e”或“E”,后跟“g”或“G”) (这也可以使用 grep 中的“-i”选项来完成,但我将此作为 REGEX 中的练习)

最后,由于我们(希望)开始看到一个模式,我们可以省略不必要的括号。由于只有一个可选字母(“E”),我们可以省略这一个。此外,由于文件只有这个模式结束,我们可以省略开始和结束括号。因此我们简单地得到:

[jJ][pP][eE]?[gG]$
Run Code Online (Sandbox Code Playgroud)

最后; 假设您还想查找带有“.gif”文件类型的文件,我们可以将其添加为第二个参数:

 ([jJ][pP][eE]?[gG])|([gG][iI][fF])$
Run Code Online (Sandbox Code Playgroud)

(在这里,我再次添加了额外的括号以提高可读性/分组。如果它们看起来很混乱,请随意删除它们。)

最后,我使用 ls 和一个管道将所有文件名发送到 (e)grep:

ls | egrep '([jJ][pP][eE]?[gG])|([gG][iI][fF])$' 
Run Code Online (Sandbox Code Playgroud)

结果:

test.gif
test.JPG
test.JpEg
test.JPEG
test.jpg
test.JPG
Run Code Online (Sandbox Code Playgroud)

第二次编辑:使用 -i 选项并省略括号,我们可以将其缩短为:

ls | egrep -i 'jpe?g|gif$'
Run Code Online (Sandbox Code Playgroud)


Gil*_*il' 12

如果您想按名称匹配文件,grep则是错误的工具。该grep实用程序在文件中查找模式;如果您关心的是文件名,则无关紧要。

Shell 通配符模式是按名称匹配文件的方法。在现代 shell 中,通配符模式具有与正则表达式相同的表达能力(即您可以用一个做什么,您可以用另一个做什么),但由于历史原因,它们具有不同的语法。

在 bash 中,您需要首先启用扩展通配符模式,通过输入此行或将其放入您的~/.bashrc

shopt -s extglob
Run Code Online (Sandbox Code Playgroud)

然后,您可以将所有.jpg.jpeg文件从当前移动到照片目录,如下所示:

mv *.@(jpg|jpeg) /path/to/photo/directory
Run Code Online (Sandbox Code Playgroud)

甚至

mv *.jp?(e)g /path/to/photo/directory
Run Code Online (Sandbox Code Playgroud)

在zsh中,如果你把setopt ksh_glob你的~/.zshrc(或在命令行输入),你可以使用上面的语法,或者你可以写

mv *.(jpg|jpeg) /path/to/photo/directory
mv *.jp(e|)g /path/to/photo/directory
Run Code Online (Sandbox Code Playgroud)

如果要递归复制当前目录及其子目录中的文件,那么在zsh中可以这样写

mv **/*.(jpg|jpeg) /path/to/photo/directory
Run Code Online (Sandbox Code Playgroud)

(注意这里复制foo/bar.jpg/path/to/photo/directory/bar.jpg.)在 bash 版本 4 中,运行shopt -s globstar,你可以写

mv **/*.@(jpg|jpeg) /path/to/photo/directory
Run Code Online (Sandbox Code Playgroud)

  • @nimrodm 你是什么意思?在 zsh 中,您可以通过在特定命令的参数前添加“noglob”前缀来禁用其参数的通配,例如“noglob lynx http://google.com/search?q=foo”。除此之外,shell 在看到命令名称是什么之前会解析命令行,例如,它首先找到结束命令的 `;` 或换行符所在的位置,然后才查看命令名称,因此如果您想在参数中传递一些特殊字符,您需要引用它们。 (2认同)

Tim*_*edy 9

您是否通过运行file $file和查看输出来获取文件类型?

tk-mbp:~ tkennedy$ file share/rally.jpg 
share/rally.jpg: JPEG image data, JFIF standard 1.01
Run Code Online (Sandbox Code Playgroud)

或者,你只是在看文件扩展名?

如果您正在查看 file 命令输出中的实际文件类型:

for file in $(find $dir -type f -exec file {} \; | grep JPEG | cut -d: -f1); do mv $file $photo_dir/ ; done
Run Code Online (Sandbox Code Playgroud)

如果您只是查看文件扩展名,则可以在以下内容中完成所有操作find

find $dir -type f -name \*jpg -o -name \*jpeg -o -name \*JPG -o -name \*JPEG -exec mv {} $photo_dir/ \;
Run Code Online (Sandbox Code Playgroud)

如果您只想知道如何将多个参数传递给 grep,您可以通过使用egrepgrep -E在 Mac OS X 上做到这一点。

find $dir | grep -E 'jpg|jpeg|JPG|JPEG'
Run Code Online (Sandbox Code Playgroud)

等等。