Perl 的重命名:GATES,Bill -> Bill Gates

3
假设我有一些文件名,如GATES,Bill.jpg,我想将它们都重命名为Bill Gates.jpg。我可以捕获这两个词。
rename 's/^(.*?), (.*?)\./$2 $1\./g' *

为了更改大小写,有一些Perl的函数:

$lower = lc("aBcDe");  # $lower is assigned "abcde" 
$upper = uc("aBcDe");  # $upper is assigned "ABCDE"
$lower = lcfirst("HELLO");  # $lower is assigned "hELLO" 
$upper = ucfirst("hello");  # $upper is assigned "Hello"

我尝试利用它们:

rename 's/^(.*?), (.*?)\./$2 ucfirst($1)\./g' *

但它不起作用。


我为Perl的rename编写了一个bash包装器,它可以预览重命名,并且只有在您接受后才会进行重命名。这是我的GitHub链接:https://github.com/bk322/bk-goodies/blob/master/bk-renames.bash - Adobe
2个回答

9

您需要在正则表达式的末尾添加“e”(eval)标志,否则该函数将不会被执行。这意味着s///表达式的整个第二部分必须是一个有效的Perl表达式(而不是有效的字符串):

rename 's/^(.*?), (.*?)\./"$2 " . ucfirst(lc($1)) . "."/ge' *

(还要注意在$2中字符串内部的额外空格)
有关此标志的更多信息,请参阅perlre文档。

干得好。+1 现在正则表达式是一个可用的语句,尽管我不知道这段代码将如何使用。 - TLP
这是Perl发行版中的“rename”(有时称为“prename”)命令。它是一个简单/短小的Perl脚本,通过应用Perl表达式来重命名命令行上指定的所有文件。 - Martijn
2
我明白了,那么这就有道理了。另一种方法是使用转义序列:s/(.+?), (.+?)\./\u\L$2\E, \u\L$1\E/。然后您将不需要使用评估(虽然我不确定在这种情况下哪种更好)。\u,\U,\l,\L 分别等同于 ucfirst、uc、lcfirst 和 lc。有关更多信息,请参见 perlreref - TLP

4

应该是:

rename 's/^(.*?), (.*?)\./$2 \u\L$1./g' *

虽然这在Unicode上并不总是完美运作。对于那些被忽略的少数情况,您需要使用更像这样的东西。

rename 's/^(\w)(\w*),\s+(\w+)\./$3 \u$1\L$2./g' *

这里是可以获取常规重命名程序的稍微更新版本的地方


它是如何更新的?我想知道 - 以便利用。 - Adobe
作为一个中度相关的问题,是否捕获第一个字母的图形符号更有意义呢?我不懂希腊语,但“组合希腊YPOGEGRAMMENI”的情况使我感到好奇。 - Hugmeir
1
@Hugmeir:有时可能会,但在这种情况下不会。 ᴄᴏᴍʙɪɴɪɴɢ ɢʀᴇᴇᴋ ʏᴘᴏɢᴇɢʀᴀᴍᴍᴇɴɪ已经是小写字母了。即使你抓住\X,将\u应用于它也只会将字形的头部变成大写字母,而这几乎永远不可能是ᴄᴏᴍʙɪɴɪɴɢ ɢʀᴇᴇᴋ ʏᴘᴏɢᴇɢʀᴀᴍᴍᴇɴɪ。唯一的例外是它跟随一个换行符字形的缺陷情况,它不允许与之组合。然后将其标题化将产生一个ɢʀᴇᴇᴋ ᴄᴀᴘɪᴛᴀʟ ʟᴇᴛᴛᴇʀ ɪᴏᴛᴀ。但实际上它并不“应该”处于那个位置。这是Grapheme_Extend中唯一有大小写代码点的情况。 - tchrist
@Adobe:使用src,然后看看。 - tchrist

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接