如何在 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
但它不会替换。一些帮助将不胜感激。
不要同时使用Bash和Perl语法,这两种语言都有晦涩难懂的语法,同时使用它们会使事情变得更糟。
Bash:
"${f%.*}.png"
珀尔:
使用 File::Basename 模块 https://perldoc.perl.org/File/Basename.html
$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
使用File::Copy
$ 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 脚本中,就没有理由去达到 shell。
更改扩展很容易“手动”完成(参见下面的库)。使用正则表达式
my $new_filename = $filename =~ s/.*\.\K.*/$new_extension/r;
.*
贪婪地匹配最后一个 .
(在模式中紧随其后),然后 \K
丢弃所有匹配项,以便我们只替换它之后的内容.或者,使用字符串结尾锚 $
my $new_filename = $filename =~ s/\.\K[^.]+$/$new_extension/r;
what 匹配并替换 .
之后字符串末尾的所有非 .
字符。
在这两种情况下,修饰符 /r
使它成为 return 新字符串并保持原始字符串不变;没有它,字符串 ($filename
) 将被原地更改。
现在更改磁盘上文件的名称。标准工具是 File::Copy
use File::Copy qw(move);
move $filename, $new_filename or die "Can't move: $!";
(如果您注意到内置 rename 保持冷静并走过它。查看其链接页面了解原因。)
一般来说,最可靠的方法当然是使用合适的库,并且可以利用一些好的库。这是有用的Path::Tiny(你需要安装)
use Path::Tiny;
my $path = path($filename);
my $new_fqn = $path->parent->child( $path->basename(qr/[^.]+/) . $new_ext );
请参阅此模块的链接文档,但这里是对上述内容的简要说明。
方法 parent
return 到最后一个组件 (file/directory) 的路径,作为 Path::Tiny
对象。然后调用它的方法 child
向它添加另一个组件。
为此,我们得到 basename
(最后一个组件,在此使用中删除了扩展名),然后将新扩展名附加到它。瞧,我们找回了替换扩展名的整个路径。这确实解析了两次路径,一次是 parent
一次是 basename
.
这样做的另一个好处是该模块也有一个 move
方法,所以
$path->move($new_fqn);
完成作业。
模块检查错误并 croaks
或抛出异常 its own class。
旧的和尝试过的 UNIX 方法是使用核心 File::Basename
use File::Basename;
my ($name, $path, $ext) = fileparse($filename, qr/\.[^.]*/);
my $new_fqn = "$path/$name.$new_ext";
然后使用File::Copy::move
重命名文件。
您在 Perl 中有双引号字符串,这意味着 $variables
是在 Perl 中插入的。就像用 Perl 写
my $xx="abc"
my $yy=${xx%.*}
你会得到同样的错误。
我正在尝试实施 Bash 参数扩展技术来替换 Perl 脚本中文件的现有扩展名。
这是我的 bash 代码,用于替换工作正常的文件扩展名:
mv "$f" "${f%.*}.png"
另一方面,我正在尝试使用 system()
:
system('mv', "$a/$fileName", "$a/${fileName%.*}".'.png');
$a
保存通过命令行参数传递的目录名称。
它抛出 "syntax error near %"
,然后是 "missing right curly or square bracket within string"
。错误信息中没有EOF。
当我不使用 %.*
时,它只是在现有文件结尾后附加 .png
但它不会替换。一些帮助将不胜感激。
不要同时使用Bash和Perl语法,这两种语言都有晦涩难懂的语法,同时使用它们会使事情变得更糟。
Bash:
"${f%.*}.png"
珀尔: 使用 File::Basename 模块 https://perldoc.perl.org/File/Basename.html
$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
使用File::Copy
$ 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 脚本中,就没有理由去达到 shell。
更改扩展很容易“手动”完成(参见下面的库)。使用正则表达式
my $new_filename = $filename =~ s/.*\.\K.*/$new_extension/r;
.*
贪婪地匹配最后一个 .
(在模式中紧随其后),然后 \K
丢弃所有匹配项,以便我们只替换它之后的内容.或者,使用字符串结尾锚 $
my $new_filename = $filename =~ s/\.\K[^.]+$/$new_extension/r;
what 匹配并替换 .
之后字符串末尾的所有非 .
字符。
在这两种情况下,修饰符 /r
使它成为 return 新字符串并保持原始字符串不变;没有它,字符串 ($filename
) 将被原地更改。
现在更改磁盘上文件的名称。标准工具是 File::Copy
use File::Copy qw(move);
move $filename, $new_filename or die "Can't move: $!";
(如果您注意到内置 rename 保持冷静并走过它。查看其链接页面了解原因。)
一般来说,最可靠的方法当然是使用合适的库,并且可以利用一些好的库。这是有用的Path::Tiny(你需要安装)
use Path::Tiny;
my $path = path($filename);
my $new_fqn = $path->parent->child( $path->basename(qr/[^.]+/) . $new_ext );
请参阅此模块的链接文档,但这里是对上述内容的简要说明。
方法 parent
return 到最后一个组件 (file/directory) 的路径,作为 Path::Tiny
对象。然后调用它的方法 child
向它添加另一个组件。
为此,我们得到 basename
(最后一个组件,在此使用中删除了扩展名),然后将新扩展名附加到它。瞧,我们找回了替换扩展名的整个路径。这确实解析了两次路径,一次是 parent
一次是 basename
.
这样做的另一个好处是该模块也有一个 move
方法,所以
$path->move($new_fqn);
完成作业。
模块检查错误并 croaks
或抛出异常 its own class。
旧的和尝试过的 UNIX 方法是使用核心 File::Basename
use File::Basename;
my ($name, $path, $ext) = fileparse($filename, qr/\.[^.]*/);
my $new_fqn = "$path/$name.$new_ext";
然后使用File::Copy::move
重命名文件。
您在 Perl 中有双引号字符串,这意味着 $variables
是在 Perl 中插入的。就像用 Perl 写
my $xx="abc"
my $yy=${xx%.*}
你会得到同样的错误。