【问题标题】:Load pictures from directory into array将目录中的图片加载到数组中
【发布时间】:2013-04-25 09:30:35
【问题描述】:

我想从目录中加载所有图片并将它们保存到数组中。

@files = `ls $ARGV[0] | grep -i -E jpe?g|gif|png$`;

这行给了我一个错误:Final $ should be \$ or $name

@files = `ls $ARGV[0] | grep -i -E \'jpe?g|gif|png$\'`;

这条线有效,但它也加载图片“img.jpg.bmp”,而这不是我想要的,甚至加载目录,这是次要的,但也很糟糕。我做错了什么?

【问题讨论】:

  • +1 for your comment“为什么使用 shell 这么难过?”

标签: perl unix grep


【解决方案1】:

您还可以使用glob 函数获取文件列表并使用grep 过滤它们。例如:

my(@files) = grep { /\.(?:jpe?g|gif|png)\z/ } glob '"*"';

或者简单地说:

my(@files) =  glob '"*.jpeg" "*.jpg" "*.gif" "*.png"';

【讨论】:

  • glob qq("$ARGV[0]/*.{jpeg,jpg,gif,png}") 怎么样? (尽管如果目录名称包含双引号,这会中断。就像您现在的解决方案一样,您必须将chdir 放入$ARGV[0] 目录以使 glob 工作)
【解决方案2】:

使用 shell 读取目录或grep 有点可悲

use autodie;
opendir my $dir, $ARGV[0];
my @files = grep !/\A\.\.?\z/ && /\.(?:jpe?g|gif|png)\z/, readdir $dir;
closedir $dir;

(我们必须手动过滤掉当前目录.和父目录..\A就像^\z有点像$,但总是在字符串结尾匹配)

`command` 的问题在于它具有双引号字符串的插值语义。 $ always 表示下一个单词或字符是变量名(正则表达式除外)。 $` 将是赛前变量,但 Perl 足够聪明,可以看出你不想要那个。您的错误消息建议的解决方案是转义$

`grep -i -E jpe?g|gif|png\$` # … and it meant this.
# It still thinks gif and png are commands
`grep -i -E '(jpe?g|gif|png)\$'` # regex correctly quoted on shell level

用单引号括起来只在 shell 级别有用,在 Perl 级别没有错误消息的来源。

在正则表达式中,行尾断言$ 只是一个普通原子,如p[abc]。它不是运算符,不像()|[]。因此,您必须强制使用括号的正确优先级。请参阅上面我提出的 Perl 解决方案中的正则表达式是如何完成的。

【讨论】:

  • @chriemmy 使用 Perl 内置函数更加冗长,但它只使用一个进程而不是三个进程(→ 性能)。使用 Perl 内置函数更安全:考虑 $ARGV[0]dir with spaces; rm -rf *; echo pwned.jpg。使用 Perl 内置函数和模块更便于移植。 Pure-Perl 代码无需修改即可在 Linux、OSX 和 Windows 上运行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-31
  • 2015-02-12
  • 1970-01-01
  • 1970-01-01
  • 2017-07-13
  • 2018-09-17
  • 1970-01-01
相关资源
最近更新 更多