如何使用正则表达式列出文件名

时间:2016-05-05 21:08:48

标签: regex bash glob

我有多个具有不同后缀的文件:

file_12
file_34
file_1245
file_4567
file_4

我只想列出后缀有四位数的文件。我知道我可以这样做

ls -l file_[0-9][0-9][0-9][0-9]

但有更好的方法吗?

5 个答案:

答案 0 :(得分:3)

这取决于更好的含义,这取决于效率和便利之间的权衡

  • 如果更好,则表示效率更高

    • 否:您已经找到了最有效的方式:globbing模式
      file_[0-9][0-9][0-9][0-9]由shell解析进程中,并将匹配的文件名传递给ls -l
    • Benjamin W.,在对该问题的评论中,有用地指出一篇解释 shell模式(通配模式)和正则表达式之间差异的文章:{ {3}}
  • 如果更好,则表示更方便

    • 使用正则表达式允许您使用量词(复制符号),这会将表达式简化为^file_[0-9]{4}$^file_\d{4}$,具体取决于正则表达式。
    • 这是以要求:
      • 使用Bash正则表达式匹配=~运算符的条件缓慢的shell循环 - 请参阅http://mywiki.wooledge.org/BashGuide/Patterns
      • 涉及理解正则表达式的另一个外部实用程序,例如grep -Eegrep) - 请参阅rob mayoff's helpful answer
        • 稍微更强大的版本,仅使用awk作为附加实用程序:
          ls -l | awk 'NF==9 && $NF ~ "^file_[0-9]{4}$"'

在一天结束时,除了效率考虑因素之外,基于正则表达式的解决方案平衡都不会简化手头的任务,因为需要额外的代码。

因此,除非您的匹配逻辑太复杂而无法使用shell(globbing)模式建模(这里不是这种情况),我建议您坚持使用原始方法。

答案 1 :(得分:2)

那是一个glob模式,但如果你想使用正则表达式,你可以使用grep:

ls -l | egrep "file_[0-9]{4}$"

请记住,文件名的开头会被忽略,因此它仍会匹配名为foo_file_1245的文件。

编辑:@ mklement0建议,我同意,如果你必须使用egrep / regex,这是一个更好的方法:

ls -l | egrep '\sfile_[0-9]{4}$'

编辑2:意识到上述陈述会错误地匹配someprefix file_1234等文件名。你可以更安全,并确保你只在最后一列(文件名)上使用egrep:

ls -l | awk '{print $9}' | egrep "^file_[0-9]{4}$"

(但坦率地说OP,此时,你的glob解决方案可能更快)

答案 2 :(得分:2)

不,没有一种特别好的方法可以做到这一点。使用shell glob的方式很容易理解,而且几乎肯定足够有效。

这是一种更糟糕的方法:使用=~命令中的[[运算符一次匹配一个文件名,如下所示:

for f in *; do
    [[ $f =~ .*[0-9]{4} ]] && ls -l "$f"
done

这是另一种更糟糕的方法:使用find命令:

find -E . -maxdepth 1 -regex '.*[0-9]{4}' -print0 | xargs -0 ls -l

答案 3 :(得分:0)

Perl救援:

perl -e 'system "ls", "-l", grep /^file_[0-9]{4}$/, glob "file_*";'

答案 4 :(得分:-1)

ls -l | grep file | grep -E '[0-9]{4}'