[英]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 中有双引号字符串,这意味着$variables
在Perl内插值。 就像写在 Perl
my $xx="abc"
my $yy=${xx%.*}
你会得到同样的错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.