一个perl脚本,适用于Snow Leopard,不再适用于Lion

时间:2011-11-08 16:59:22

标签: regex perl greedy

我曾经在桌面上采用以下格式的任意文件集:

  

Screen Shot 2011-11-08 at 8.10.23 AM.png

     

Screen Shot 2011-11-08 at 8.08.57 AM.png

在它们上运行Perl脚本并将它们重命名为

  

SS-2011-11-08 at 8.10.23 AM.png

     

SS-2011-11-08 at 8.08.57 AM.png

这停止了工作,没有重命名。现在我必须改变它,我希望它改为:

  

β-2011.11.08.at.8.10.23.AM.png

     

β-2011.11.08.at.8.08.57.AM.png

  • 将“Screen Shot”替换为“ss”
  • 将所有-替换为.
  • 将所有空格替换为.

我知道这与贪婪有关,但我没有写这个,无论我做多少摆弄我似乎无法让它发挥作用。我生命中的几个小时都用过perl。我想我可以在PHP中用几行来完成这个,但是想学习如何将它保存在perl中,因为能够调试总是好的。我查找了regs格式规则,但它们没有应用。无论是Mac OS X Lion中的某些东西都搞砸了,或者Snow Leopard允许发生不应该发生的事情。

谢谢大家!

这是我到目前为止所做的:

 #!/usr/bin/perl -w

 chdir( "/Users/me/Desktop" ) or die;
 my @files = ();
 print "after my \@files array\n";
 print @files;

 while ( <*> ) {
    push @files, $_ if m!^Screen Shot (.*) at (.*)\.png!;
 }


 foreach my $f ( @files ) {
    my $new = $f;
    $new =~ s!^SS (.*) at (.*)\.png!ss-$1\_$2.png!;
    print "$f -> $new\n";
    rename ( $f, $new ) or die;
 }

4 个答案:

答案 0 :(得分:1)

只需将替换更改为此

即可
$new =~ s/Screen\.Shot\.(.*)\.at\.(.*)/ss-$1.at.$2/;

并在之前添加其他替换

$new =~ s/[- ]/./g;  # Replace all dashes and spaces to dots

答案 1 :(得分:0)

当您将所有文件添加到与以下正则表达式匹配的数组时:

/^Screen Shot (.*) at (.*)\.png/

然后尝试替换上述数组中的每个文件,如下所示:

/^SS (.*) at (.*)\.png/

你怎么可能期望这个工作?

答案 2 :(得分:0)

第一个表达式(在if中)

m!^Screen Shot \d+-\d+-\d+ at \d+\.\d+\.\d+\s[AP]M\.png$!

第二个表达式(虽然我认为技术上是多余的,因为除了捕获组之外匹配表达式是相同的)将是:

s!^Screen Shot (\d+)-(\d+)-(\d+) at (\d+)\.(\d+)\.(\d+)\s([AP]M)\.png$!ss-$1.$2.$3.at.$4.$5.$6.$7.png!

至少对我有用!

如果您希望我为您分解,请问!

答案 3 :(得分:0)

我正在运行Snow Leopard,我的屏幕截图保存为Screen shot ...(请注意s上的小写shot)。 Lion现在使用大写S吗?如果是这样,并且您的原始脚本使用了小写s,那么这可能就是破坏它的原因。无论哪种方式,让我们解决它。

您的替换

$new =~ s!^SS (.*) at (.*)\.png!ss-$1\_$2.png!;

正在查找以SS开头的文件名,后跟一个空格,但听起来您想要更改以SS开头,后跟-的文件名或 Screen [Ss]hot后跟一个空格。

另外,正如@FailedDev指出的那样,您的while循环只会将^Screen Shot (.*) at (.*)\.png@files数组匹配的文件添加到您的foreach数组中,因此您SS循环永远不会看到以#!/usr/bin/perl -w use strict; # ALWAYS! chdir( "/Users/me/Desktop" ) or die("Could not chdir() to ~/Desktop: $!"); foreach my $f (<*>) { my $new = $f; if ($new =~ s!^(?:SS-|Screen [Ss]hot )([\d-]+) at ([\d\.]+) ([AP]M)\.png!ss-$1.at.$2.$3.png!) { $new =~ s/\-/\./g; print "$f -> $new\n"; rename ( $f, $new ) or die("Could not rename $f to $new: $!"); } } 开头的文件。

用以下代码替换您的代码:

^

帮助您了解正在发生的事情:

  • s!之后的|表示只查看要替换的文本的开头,在本例中为文件名
  • SS-Screen [Ss]hot之间的(?:) [按SS-分组]表示查找Screen [Ss]hot()
  • 三个捕获组[由?: 包围而 $1]不包含空格,因此$2$3和{替换中的{1}}将不包含空格。
  • if语句确保if块中的代码仅在文件名匹配且实际发生替换时才执行。