如何更改文件名

时间:2017-02-10 11:37:48

标签: regex perl

使用Perl和rename,我想更改为小写或大写,除文件名中的最后N个字符外。

例如,如果N是10并且需要大写,那么 foo_1_bar_2-abcdef.txt应该成为FOO_1_BAR_2-abcdef.txt

我尝试了rename "y/a-z{.10}$/A-Z/" *之类的内容,但y运算符似乎不想{.10}

3 个答案:

答案 0 :(得分:2)

我更倾向于使用\U转义序列而不是uc以及替换的表达式模式。前瞻性前瞻也消除了重新组合字符串

的未更改部分的需要
use strict;
use warnings 'all';
use feature 'say';

my $s = join '', 'a' .. 'z';

$s =~ s/(.+)(?=.{10})/\U$1/;

say $s;

输出

ABCDEFGHIJKLMNOPqrstuvwxyz

但是,如果您的文件名始终是给定的形式,即您总是希望在连字符之前将部分大写,那么您应该通过上下文而不是计算字符数来保持不变

use strict;
use warnings 'all';
use feature 'say';

my $s = 'foo_1_bar_2-abcdef.txt';

$s =~ s/^([^-]+)/\U$1/;

say $s;

输出

FOO_1_BAR_2-abcdef.txt

答案 1 :(得分:1)

我认为这是因为你不了解y///正在做什么。

这是基于字符的替换,所以你说a-z中的'transliterate' - > A-Z

在这种情况下,{.10}只是另一组要替换的字符(但左侧没有匹配。

更清楚地了解发生的事情:

y/a-z{.10}$/A-Zlmnopq/;

在你的字符串上会成功:

FOO_n_BAR_2-ABCDEFmTXT

因为'0'和'1'映射到字符。

要做你想做的事,你可以像这样解决它:

 s/(.*)(.{10})/uc ($1).$2/e;

E.g:

#!/usr/bin/env perl
use strict;
use warnings;

while (<DATA>) {
   s/(.*)(.{10})/uc ($1).$2/e;
   print;
}

__DATA__
foo_1_bar_2-abcdef.txt

(上面你不需要行结束锚,因为.*正则表达式是贪婪的。)

这会输出:

FOO_1_BAR_2-abcdef.txt

虽然您可能会发现更好/更适合处理分隔符锚定(例如-text,因为这似乎是您的目标。(我猜):

s/(.*-)/uc ($1)/e;

答案 2 :(得分:1)

s///解决方案外,这似乎也是substr的一项轻松工作:

my $n = 10; # number of chars left untouched at the end
substr $s, 0, -$n, lc substr $s, 0, -$n;