0

我正在尝试重命名目录中的一堆文件,但我被困在其中的正则表达式部分。

我想从出现在开头的文件名中删除某些字符。

示例 1:_00-author--book_revision_

预期的:Author - Book (Revision)

到目前为止,我可以使用正则表达式删除下划线并将第一个字母大写

$newfile =~ s/_/ /g;
$newfile =~ s/^[0-9]//g;
$newfile =~ s/^[0-9]//g;
$newfile =~ s/^-//g;
$newfile = ucfirst($newfile);

这不是一个好方法。我需要帮助删除所有字符,直到您点击第一个字母,当您点击第一个“-”时,我想在“-”之前和之后添加一个空格。另外,当我点击第二个“-”时,我想用“(”替换它。

非常感谢任何有关采取正确方法的指导、提示甚至建议。

4

4 回答 4

1

你的指示和你的例子不匹配。

根据您的指示,

s/^[^\pL]+//;    # Remove everything until first letter.
s/-/ - /;        # Replace first "-" with " - "
s/-[^-]*\K-/(/;  # Replace second "-" with "("

根据你的例子,

s/^[^\pL]+//;
s/--/ - /;
s/_/ (/;
s/_/)/;
s/(?<!\pL)(\pL)/\U$1/g;
于 2012-05-02T05:58:32.690 回答
1
$filename =~ s,^_\d+-(.*?)--(.*?)_(.*?)_$,\u\1 - \u\2 (\u\3),;

我的 Perl 解释器(使用严格和警告)说最好这样写:

$filename =~ s,^_\d+-(.*?)--(.*?)_(.*?)_$,\u$1 - \u$2 (\u$3),;

第一个可能是因为它的味道更sedish!(当然,两个版本的工作原理都是一样的。)

解释(根据stema的要求):

$filename =~ s/
  ^       # matches the start of the line
  _\d+-   # matches an underscore, one or more digits and a hypen minus
  (.*?)-- # matches (non-greedyly) anything before two consecutive hypen-minus
          #   and captures the entire match (as the first capture group)
  (.*?)_  # matches (non-greedyly) anything before a single underscore and
          #  captures the entire match (as the second capture group)
  (.*?)_  # does the same as the one before (but captures the match as the
          #  third capture group obviously)
  $       # matches the end of the line
/\u$1 - \u$2 (\u$3)/x;

替换规范只是告诉 Perl 插入从 1 到 3的\u${1..3}捕获组,并且它们的第一个字符大写。如果您想将整个匹配(在捕获的组中)设为大写,则必须\U改用。

x标志打开详细模式,它告诉 Perl 解释器我们要使用#注释,所以它会忽略这些(以及正则表达式中的任何空格 - 所以如果你想匹配一个空格,你必须使用\s或者\)。不幸的是,我不知道如何告诉 Perl 忽略 * replacement* 规范中的空白 - 这就是我将其写在一行的原因。

(另请注意,我已将s终止符从更改,/- 如果我使用,打开详细模式的 Perl 对我咆哮......不完全确定为什么。)

于 2012-05-02T06:05:31.720 回答
1

那么你想大写新文件名的所有组成部分,还是只大写第一个?你的问题在这一点上是不一致的。

请注意,如果您在 Linux 上,您可能有rename命令,它将接受一个 perl 表达式并使用它为您重命名文件,如下所示:

rename 'my ($a,$b,$r);$_ = "$a - $b ($r)" 
  if ($a, $b, $r) = map { ucfirst $_ } /^_\d+-(.*?)--(.*?)_(.*?)_$/' _*
于 2012-05-02T06:18:58.343 回答
0

如果他们都遵循该格式,请尝试:

my ($author, $book, $revision) = $newfiles =~ /-(.*?)--(.*?)_(.*?)_/;

print ucfirst($author ) . " - $book ($revision)\n";
于 2012-05-02T06:02:56.657 回答