【问题标题】:how to loop through files that match a regular expression in a unix shell script如何遍历与 unix shell 脚本中的正则表达式匹配的文件
【发布时间】:2016-08-13 03:23:09
【问题描述】:

我希望能够遍历与特定模式匹配的文件列表。我可以让 unix 使用带有正则表达式的 ls 和 egrep 列出这些文件,但是我找不到将其转变为迭代过程的方法。我怀疑使用 ls 不是答案。任何帮助将不胜感激。

我当前的 ls 命令如下所示:

ls | egrep -i 'MYFILE[0-9][0-9]([0][1-9]|1[0-2])([0][1-9]|[12][0-9]|[3][01]).dat'

我希望以上匹配:

  • MYFILE160418.dat
  • myFILE170312.DAT
  • MyFile160416.DaT

但不是:

  • MYOTHERFILE150202.DAT
  • 我的文件.dat
  • myfile.csv

谢谢,

保罗。

【问题讨论】:

  • 嗨@paul-frith,您应该以whilefor开头。使用示例中的计数器 -> tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-7.html
  • 在许多情况下,您不需要显式循环,因为您可以通过管道将参数传递给另一个程序,可能使用xargs
  • 非常感谢 - 我没有意识到你可以在 for 循环中使用 ls。
  • 试试:ls | egrep -i 'MYFILE\d{6}\.dat'
  • Saleem,虽然更简洁,但我相信这会给出更宽松的匹配标准,使用您的方法将允许大于 12 的月份和大于 31 的日期。

标签: regex bash shell unix


【解决方案1】:

您可以将 (GNU) find 与正则表达式搜索选项一起使用,而不是解析 ls

find . -regextype "egrep" \
       -iregex '.*/MYFILE[0-9][0-9]([0][1-9]|1[0-2])([0][1-9]|[12][0-9]|[3][01]).dat' \
       -exec [[whatever you want to do]] {} \;

[[whatever you want to do]] 是您要对文件名执行的命令。

来自手册页

-regextype type
          Changes  the regular expression syntax understood by -regex and -iregex tests 
          which occur later on the command line.  Currently-implemented types are 
          emacs (this is the default),posix-awk, posix-basic, posix-egrep and 
          posix-extended.

  -regex pattern
          File name matches regular expression pattern.  This is a match on the whole 
          path, not a search.  For example, to match a file named `./fubar3', you can 
          use the regular expression
          `.*bar.' or `.*b.*3', but not `f.*r3'.  The regular expressions understood by 
          find are by default Emacs Regular Expressions, but this can be changed with 
          the -regextype option.

  -iregex pattern
          Like -regex, but the match is case insensitive.

【讨论】:

  • 有趣 - 有趣的是,“find”是我最初期待的,但我无法让我的正则表达式工作。 -regextype "egrep" 是我需要的!
【解决方案2】:

根据 Andy K 提供的链接,我使用以下内容根据我的匹配条件进行循环:

for i in $(ls | egrep -i 'MYFILE[0-9][0-9]([0][1-9]|1[0-2])([0][1-9]|[12][0-9]|[3][01]).dat' ); do             
 echo item: $i;         
done

【讨论】:

  • 我看过这个,似乎解析 ls 是个坏主意,因为 UNIX 允许文件名中的几乎任何字符,包括换行符等。但是鉴于我是正则表达式匹配,当然在这种情况下,这个问题得到了缓解。还有其他不解析 ls 的原因吗?
  • 不要使用ls 输出任何东西。 ls 是一个交互式查看目录元数据的工具。任何用代码解析ls 输出的尝试都会被破坏。 Glob 更加简单和正确:for file in *.txt。阅读Parsing ls
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-17
  • 2012-01-25
  • 1970-01-01
  • 1970-01-01
  • 2010-12-07
  • 1970-01-01
  • 2018-11-27
相关资源
最近更新 更多