bash中的正则表达式无效

时间:2014-09-02 11:13:29

标签: regex bash

bash中是否有任何方法可以匹配那样的模式

[0-9]{8}.*.jpg

我已经为以下模式匹配编写了上述内容 “前八个字符应为数字,其余部分为任意内容,以.jpg结尾” 但上述情况无效。如果我以下面的方式写作它正在工作

[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].*.jpg

现在假设我想要前20个字符必须是数字我应该重复[0-9] 20次..我认为有一个更好的解决方案,我不知道......

如果有人知道请帮助....

3 个答案:

答案 0 :(得分:3)

您可以在find中使用正则表达式:

find test -regextype posix-extended -regex "^[0-9]{8}.*.jpg$"

测试

$ touch test/12345678aaa.jpg
$ touch test/1234567aaa.jpg

$ find test -regextype posix-extended -regex ".*/[0-9]{8}.*"
test/12345678aaa.jpg

如果它与previous question相关,您可以使用:

for file in $(find test -regextype posix-extended -regex ".*/[0-9]{8}.*")
do
   echo "my file is $file"
done

如果您在其中创建目录和文件,则可能会出现更多匹配项:

$ mkdir test/123456789.dir
$ touch test/123456789.dir/1234567890.jpg

您可以按-type f进行过滤,以便获取文件:

$ find test -type f -regextype posix-extended -regex ".*/[0-9]{8}.*"
test/12345678aaa.jpg
test/123456789.dir/1234567890.jpg

和/或指定find的深度,以便它不包含子目录:

$ find test -maxdepth 1 -type f -regextype posix-extended -regex ".*/[0-9]{8}.*"
test/12345678aaa.jpg

答案 1 :(得分:2)

看起来您正在尝试从正则表达式生成文件名列表。你可以这样做,但据我所知,不是直接来自Bash。相反,请使用find

find -E . -regex '.*/[0-9]{8}.*\.jpg' -depth 1

类似的东西适用于我的Mac OS X系统;在Linux上,当前目录的.是可选的,或者您可以指定要搜索的其他目录。我添加了-depth 1以避免降级到子目录。

答案 2 :(得分:1)

有点迟到的答案。

Bash的文件名扩展模式(称为 globbing )拥有自己的规则。它们以两种形式存在:

  • simple globbing
  • 扩展通配(如果您已启用shopts -s extglob

您可以阅读有关规则的详细信息,例如here。 (3.5.8.1模式匹配)

你应该记住,通配规则不是传统的正则表达式(你可能知道grepsed等),特别是它们是不是perl的(扩展的)正则表达式。

因此,如果你想使用文件名扩展(也称为globbing),你就会遇到上述两个(简单/扩展)模式规则。当然,bash知道正则表达式,但用于文件名扩展(通配)。

所以,你可以做下一个:

shopt -s globstar        #if you haven't already enabled - for the ** expansion
regex="[0-9]{8}.*\.jpg"
for file in ./**/*.jpg   #will match all *.jpg recusrively (globstar)
do
    #try the regex matching
    [[ $file =~ $regex ]] || continue  #didn't match

    #matched! - do something with the file
    echo "the $file has at least 8 digits"
done

或者您可以使用带有内置正则表达式匹配规则的find命令(请参阅其他答案),或使用类似perl的正则表达式的grep,例如:

find somewhere -type f -name \*.jpg -maxdepth 1 -print0 | grep -zP '/\d{8}.*.jpg'

速度:对于大树,find更快。至少在我的笔记本上,其中:

while IFS= read -d $'\0' -r file
do
    echo "$file"
done < <(find ~/Pictures -name \*.JPG -print0 | grep -zP 'P\d{4}.*\.JPG')

运行real 0m1.593s

regex="P[0-9]{4}.*\.JPG"
for file in ~/Pictures/**/*.JPG
do
    [[ $file =~ $regex ]] || continue  #didn't match

    echo "$file"
done

运行real 0m3.628s秒。

在小树上,恕我直言最好使用构建bash正则表达式。 (也许,我更喜欢它,因为我喜欢./**/*.ext扩展,并且在变量中正确获取所有文件名,无论空格等,而不关心-print0read -d $'\0;等...)