4

Perl 重命名实用程序在日常文件工作中做得很好,尤其是在我不时检查我的 MP3 收藏时。

有些人有一个可怕的习惯,总是把艺术家的名字大写,就像这样

03 - ARTIST NAME - Song Title.mp3

我希望将其重命名为看起来更平静的混合案例,就像这样

03 - Artist Name - Song Title.mp3

但是,它也应该以一种智能的方式完成。

可能有法语或意大利语标题,例如:

05 - JEAN BAGUETTE - Honi soit qui mal y pense.mp3

或者

07 - SIGNORE AL FORNO - Pazzi sono tutti i calciatori.mp3

因此,我希望这些在 之后变成混合大小写-,只有艺术家部分。

一种行不通的方法是

rename 's/(\d{1,2} - )([A-Z ]+)([\s\S]+)/$1lc($2)$3/' filename

无论如何我都会发布它,因为它总能让你更好地了解我正在尝试做什么。

我也尝试用$2临时变量替换 (因为我不允许更改 $2 因为它是只读的)并lc()在打印结果之前执行此操作,但我没有成功。但无论如何,我是一个 Perl 初学者。

4

2 回答 2

3

我知道的最清楚的方法是进行两阶段评估(使用/e修饰符)替换。

在下面的代码中,外部替换选择艺术家姓名,包括其边界连字符并替换它。

内层采用$1- 艺术家姓名 - 并将非空格字符的每个子序列替换为相同的字符串,首先小写lc字母,然后大写字母ucfirst

就目前而言,该程序将打印之前和之后的名称。#从重命名行中删除以进行重命名。

use strict;
use warnings;

my @data = (
  '05 - JEAN BAGUETTE - Honi soit qui mal y pense.mp3',
  '07 - SIGNORE AL FORNO - Pazzi sono tutti i calciatori.mp3',
);

for my $file (@data) {

  (my $new = $file) =~ s{(-[^-]+-)}{
    (my $artist = $1) =~ s/(\S+)/ucfirst lc $1/eg;
    $artist;
  }e;

  print "$file\n";
  print "$new\n";
  print "\n";
  # rename $file, $new;
}

输出

05 - JEAN BAGUETTE - Honi soit qui mal y pense.mp3
05 - Jean Baguette - Honi soit qui mal y pense.mp3

07 - SIGNORE AL FORNO - Pazzi sono tutti i calciatori.mp3
07 - Signore Al Forno - Pazzi sono tutti i calciatori.mp3

更新

您可能喜欢的另一种方法是在连字符上拆分文件名,编辑第二部分并将它们重新连接在一起。

上面的主循环变成

for my $file (@data) {

  my @file = split /-/, $file;
  $file[1] =~ s/(\S+)/ucfirst lc $1/eg;
  my $new = join '-', @file;

  print "$file\n";
  print "$new\n";
  print "\n";
  # rename $file, $new;
}

功能和输出不变。


更新 2

我刚刚尝试使用 /-.*?-/ 然后使用 substr($_, $-[0], $+[0]) 作为 =~ s/// 的左值,但遗憾的是它没有用

这似乎是一个很好的想法,我不得不尝试一下。

您的调用substr是错误的,因为$-[0]$+[0]是字符串的偏移量。第三个参数substr必须是字符串长度,所以你需要写substr($_, $-[0], $+[0] - $-[0])

此代码工作正常,并再次产生与以前相同的结果

for my $file (@data) {

  next unless $file =~ /-[^-]+-/;
  my $new = $file;
  substr($new, $-[0], $+[0]-$-[0]) =~ s/(\S+)/ucfirst lc $1/eg;

  print "$file\n";
  print "$new\n";
  print "\n";
  # rename $file, $new;
}
于 2012-06-12T23:03:35.967 回答
2

ucfirst您可以在正则表达式中使用( \u) 和lc( )的转义序列\L,并结合需要进一步向前冲刺的前瞻断言:

perl -pe 's/(\w)(\w+)(?=.*-)/\u$1\L$2/g'

如果您想更正确,可以使用\pL(字母) 代替\w. 我认为这将适用于该rename工具。

ETA:更新为使用\u而不是\U.

于 2012-06-13T00:42:18.900 回答