【问题标题】:Escaping brackets in file names文件名中的转义括号
【发布时间】:2011-05-07 21:05:11
【问题描述】:

我有一些文件命名如下:file (2).jpg。我正在编写一个小的 Perl 脚本来重命名它们,但由于括号没有被替换,我得到了错误。 所以。有人可以告诉我如何转义字符串中的所有括号(和空格,如果它们引起问题),以便我可以将其传递给命令。脚本如下:

#将所有jpgs加载到一个数组中。 @pix = `ls *.JPG`; foreach $pix (@pix) { #让你知道它正在工作 print "处理照片".$pix; $pix2 = $pix; $pix2 =~ \Q$pix\E; # 问题线 #使用程序exiv2重命名带有时间戳的文件 system("exiv2 -r %Y_%m%d_%H%M%S $pix2"); }

错误是这样的:

无法在 script.sh 行 [问题行] 处调用没有包或对象引用的方法“Q”。

这是我第一次使用正则表达式,所以我正在寻找解释该做什么以及给出答案的答案。感谢您的帮助。

【问题讨论】:

  • Perl 中的字符串需要引号。 $pix2 = "\Q$pix\E";
  • 愚蠢的我。你可以看出我以前从未使用过 Perl。
  • 请注意,您应该使用String::ShellQuote 而不是\Q...\E 来安全地转义文件名,请参阅stackoverflow.com/q/3796682/23118
  • 虽然在这种情况下,您可以通过在列表模式下使用系统来避免整个转义,system("exiv2", "-r", "%Y_%m%d_%H%M%S", "$pix");

标签: regex perl escaping


【解决方案1】:

为什么不使用简单的?

find . -name \*.JPG -exec exiv2 -r "%Y_%m%d_%H%M%S" "{}" \;

附: \Q 禁用模式元字符直到 \E 在正则表达式中

例如,如果你想匹配一个路径“../../../somefile.jpg”,你可以这样写:

$file =~ m:\Q../../../somefile.jpg\E:;

而不是

$file =~ m:\.\./\.\./\.\./somefile\.jpg:; #e.g. escaping all "dots" what are an metacharacter for regex.

【讨论】:

    【解决方案2】:

    我发现了这个由 Larry Wall 不久前编写的 perl 重命名脚本......它可以满足您的需求,而且还有很多其他功能。我保留在我的 $PATH 中,并且每天都使用它...

    #!/usr/bin/perl -w
    
    use Getopt::Std;
    
    getopts('ht', \%cliopts);
    do_help() if( $cliopts{'h'} );
    
    #
    # rename script examples from lwall:
    #       pRename.pl 's/\.orig$//' *.orig
    #       pRename.pl 'y/A-Z/a-z/ unless /^Make/' *
    #       pRename.pl '$_ .= ".bad"' *.f
    #       pRename.pl 'print "$_: "; s/foo/bar/ if <stdin> =~ /^y/i' *
    
    $op = shift;
    for (@ARGV) {
       $was = $_;
       eval $op;
       die $@ if $@;
       unless( $was eq $_ ) {
          if( $cliopts{'t'} ) {
             print "mv $was $_\n";
          } else {
             rename($was,$_) || warn "Cannot rename $was to $_: $!\n";
          }
       }
    }
    
    sub do_help {
       my $help = qq{
       Usage examples for the rename script example from Larry Wall:
            pRename.pl 's/\.orig\$//' *.orig
            pRename.pl 'y/A-Z/a-z/ unless /^Make/' *
            pRename.pl '\$_ .= ".bad"' *.f
            pRename.pl 'print "\$_: "; s/foo/bar/ if <stdin> =~ /^y/i' *
    
       CLI Options:
       -h      This help page
       -t      Test only, do not move the files
          };
       die "$help\n";
       return 0;
    }
    

    【讨论】:

    • 感谢迈克的帮助,但我自己搞定了 - quotemeta() 创造了奇迹。这个脚本看起来不错,但不适合我的需要。为努力 +1 :-)
    • 您可以发布自己的答案并接受它,如果您愿意...这也会让您获得 2 分 :)
    • 连偷偷摸摸都不算...其实就是encouraged
    猜你喜欢
    • 2012-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-04
    • 2014-06-10
    • 2011-06-27
    • 2012-02-16
    相关资源
    最近更新 更多