1

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

屏幕截图 2011-11-08 在 8.10.23 AM.png

屏幕截图 2011-11-08 在 8.08.57 AM.png

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

SS-2011-11-08 上午 8.10.23.png

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

这停止工作并且没有重命名发生。现在我必须更改它,我希望它更改为:

ss-2011.11.08.at.8.10.23.AM.png

ss-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

4 回答 4

1

只需将替换更改为此

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

并在它之前添加另一个替换:

$new =~ s/[- ]/./g;  # Replace all dashes and spaces to dots
于 2011-11-08T17:24:53.353 回答
0

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

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

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

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

你怎么能指望这行得通?

于 2011-11-08T17:37:38.490 回答
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!

至少对我有用!

如果你想让我为你分解它,请问!

于 2011-11-08T18:27:33.523 回答
0

我正在运行 Snow Leopard,我的屏幕截图保存为Screen shot ...(注意 上的小写字母sshot。Lion 现在是否使用大写字母S?如果是这样,并且您的原始脚本使用了小写s,那么这可能就是破坏它的原因。不管怎样,让我们​​修复它。

你的替代品

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

正在寻找以 开头SS,后跟空格的文件名,但听起来您想更改以 开头,后跟SSa后跟空格的文件名。- 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: $!");
    }
}

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

  • ^after表示只查看s!要替换的文本的开头,在这种情况下是文件名
  • |betweenSS-和[ Screen [Ss]hotgrouped by (?:)] 表示查找SS-Screen [Ss]hot
  • () 三个捕获组 [ 被不带]包围?:不包含空格,因此$1,$2$3在您的替换中将不包含空格。
  • if语句确保if块内的代码仅在文件名匹配并且实际发生替换时才执行。
于 2011-11-08T19:00:46.523 回答