繁体   English   中英

Perl中如何使用Shell参数扩展?

[英]How to use Shell Parameter Expansion in Perl?

我正在尝试实现 Bash 参数扩展技术来替换 Perl 脚本中文件的现有扩展名。

这是我的 bash 代码,用于替换工作正常的文件扩展名:

mv "$f" "${f%.*}.png"

另一方面,我正在尝试使用system()在 Perl 脚本中使用它:

system('mv', "$a/$fileName", "$a/${fileName%.*}".'.png');

$a保存通过命令行参数传递的目录名称。

它抛出"syntax error near %"后跟"missing right curly or square bracket within string" 错误消息中没有 EOF。

当我不使用%.*时,它只是在现有文件结束后附加.png但它不会替换。 一些帮助将不胜感激。

所以你想替换扩展名——来改变一个文件名。 一旦您在 Perl 脚本中,就没有理由为此使用 shell。

更改扩展很容易“手动”完成(参见下面的库)。 使用正则表达式

my $new_filename = $filename =~ s/.*\.\K.*/$new_extension/r;

.*贪婪地匹配到最后一个. (在模式中),然后\K删除所有匹配项,以便我们只替换它后面的内容。 或者,使用字符串结尾锚$

my $new_filename = $filename =~ s/\.\K[^.]+$/$new_extension/r;

什么匹配和替换所有非. a 之后字符串末尾的字符. . 在这两种情况下,修饰符/r使它返回新字符串并保持原始字符串不变; 没有它,字符串( $filename )将就地更改。

现在更改磁盘上文件的名称。 标准工具是File::Copy

use File::Copy qw(move);

move $filename, $new_filename  or die "Can't move: $!";

(如果您注意到内置的重命名,请保持冷静并走过它。可以看到它的链接页面。)


一般来说,最可靠的方法当然是使用合适的库,并且有一些好的库可以用于此目的。 这是有用的Path::Tiny (您需要安装)

use Path::Tiny;

my $path = path($filename);

my $new_fqn = $path->parent->child( $path->basename(qr/[^.]+/) . $new_ext );

请参阅此模块的链接文档,但这里是对上述内容的简要说明。

方法parent返回到最后一个组件(文件/目录)的路径,作为Path::Tiny object。 然后调用它的方法child向它添加另一个组件。

为此,我们得到基本名称(最后一个组件,在此使用中去掉了扩展名),然后是basename的新扩展名。 瞧,我们得到了替换扩展名的整个路径。 这确实会解析路径两次,一次用于parent ,一次用于basename

这样做的另一个好处是该模块也有一个move方法,所以

$path->move($new_fqn);

完成工作。

该模块检查错误并发出呱呱声或抛出其自己的 class croaks


旧的和尝试过的 UNIX 方式是使用核心File::Basename

use File::Basename;

my ($name, $path, $ext) = fileparse($filename, qr/\.[^.]*/); 

my $new_fqn = "$path/$name.$new_ext";

然后使用File::Copy::move重命名文件。

不要同时使用 Bash 和 Perl 语法,这两种语言都有晦涩难懂的语法,同时使用它们会使事情变得更糟。

Bash:

"${f%.*}.png"

Perl:使用 File::Basename 模块https://perldoc.perl.org/File/Basename.Z5E056FDC70D52768

$f_new=fileparse($f_old,qr/\.[^.]*/);
$f_new.=".png";

Bash:

mv

Perl:

rename / File::Copy (see comment)

放在一起(单行 Perl 中的演示):将 foo.jpg 重命名为 foo.png

使用重命名:

$ perl -MFile::Basename -e '$f_old=$ARGV[0];$f_new=fileparse($f_old,qr/\.[^.]*/);$f_new.=".png";rename $f_old, $f_new' foo.jpg

使用文件::复制

$ perl -MFile::Copy -MFile::Basename -e '$f_old=$ARGV[0];$f_new=fileparse($f_old,qr/\.[^.]*/);$f_new.=".png";File::Copy::move $f_old, $f_new' foo.jpg

您在 Perl 中有双引号字符串,这意味着$variablesPerl内插值。 就像写在 Perl

my $xx="abc"
my $yy=${xx%.*}

你会得到同样的错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM