如何在脚本中用 Perl 替换文件中的字符串(而不是在命令行中)
How to replace string in a file with Perl in script (not in command line)
我想替换文件中的字符串。我当然可以使用
perl -pi -e 's/pattern/replacement/g' file
但我想用脚本来完成。
除了system("perl -pi -e s/pattern/replacement/g' file")
还有其他方法吗?
-i
利用了您仍然可以读取未链接的文件句柄的优势,您可以在 perlrun 中看到它使用的代码。自己做同样的事情。
use strict;
use warnings;
use autodie;
sub rewrite_file {
my $file = shift;
# You can still read from $in after the unlink, the underlying
# data in $file will remain until the filehandle is closed.
# The unlink ensures $in and $out will point at different data.
open my $in, "<", $file;
unlink $file;
# This creates a new file with the same name but points at
# different data.
open my $out, ">", $file;
return ($in, $out);
}
my($in, $out) = rewrite_file($in, $out);
# Read from $in, write to $out as normal.
while(my $line = <$in>) {
$line =~ s/foo/bar/g;
print $out $line;
}
您可以使用
sed 's/pattern/replacement/g' file > /tmp/file$$ && mv /tmp/file$$ file
一些 sed 版本支持 -i 命令,因此您不需要 tmp 文件。 -i 选项将为您制作临时文件并移动,基本上它是相同的解决方案。
另一种解决方案 (Solaris/AIX) 可以结合 vi 使用 here 构造:
vi file 2>&1 >/dev/null <@
1,$ s/pattern/replacement/g
:wq
@
我不喜欢 vi 解决方案。当您的模式具有 / 或其他特殊字符时,将很难调试出了什么问题。当 replacement
由 shell 变量给出时,您可能需要先检查内容。
您可以很容易地复制 Perl 使用 -i
开关所做的事情。
{
local ($^I, @ARGV) = ("", 'file');
while (<>) { s/foo/bar/; print; }
}
您可以试试下面的简单方法。看看它是否最符合您的要求。
use strict;
use warnings;
# Get file to process
my ($file, $pattern, $replacement) = @ARGV;
# Read file
open my $FH, "<", $file or die "Unable to open $file for read exited $? $!";
chomp (my @lines = <$FH>);
close $FH;
# Parse and replace text in same file
open $FH, ">", $file or die "Unable to open $file for write exited $? $!";
for (@lines){
print {$FH} $_ if (s/$pattern/$replacement/g);
}
close $FH;
1;
file.txt:
Hi Java, This is Java Programming.
执行:
D:\swadhi\perl>perl module.pl file.txt Java Source
file.txt
Hi Source, This is Source Programming.
您可以处理问题中的用例,而无需重新创建 -i
标志的功能或创建一次性变量。将标志添加到 Perl 脚本的 shebang 并读取 STDIN:
#!/usr/bin/env perl -i
while (<>) {
s/pattern/replacement/g;
print;
}
用法:保存脚本,使其可执行(使用 chmod +x
),以及 运行
path/to/the/regex-script test.txt
(或 regex-script test.txt
如果脚本保存到 $PATH 中的目录。)
超越问题:
如果你需要运行多次顺序替换,那就是
#!/usr/bin/env perl -i
while (<>) {
s/pattern/replacement/g;
s/pattern2/replacement2/g;
print;
}
如问题示例,源文件将不会被备份。就像在 -e
oneliner 中一样,您可以通过向 -i
标志添加 backupExtension 来备份到 file.<backupExtension>
。例如,
#!/usr/bin/env perl -i.bak
我想替换文件中的字符串。我当然可以使用
perl -pi -e 's/pattern/replacement/g' file
但我想用脚本来完成。
除了system("perl -pi -e s/pattern/replacement/g' file")
还有其他方法吗?
-i
利用了您仍然可以读取未链接的文件句柄的优势,您可以在 perlrun 中看到它使用的代码。自己做同样的事情。
use strict;
use warnings;
use autodie;
sub rewrite_file {
my $file = shift;
# You can still read from $in after the unlink, the underlying
# data in $file will remain until the filehandle is closed.
# The unlink ensures $in and $out will point at different data.
open my $in, "<", $file;
unlink $file;
# This creates a new file with the same name but points at
# different data.
open my $out, ">", $file;
return ($in, $out);
}
my($in, $out) = rewrite_file($in, $out);
# Read from $in, write to $out as normal.
while(my $line = <$in>) {
$line =~ s/foo/bar/g;
print $out $line;
}
您可以使用
sed 's/pattern/replacement/g' file > /tmp/file$$ && mv /tmp/file$$ file
一些 sed 版本支持 -i 命令,因此您不需要 tmp 文件。 -i 选项将为您制作临时文件并移动,基本上它是相同的解决方案。
另一种解决方案 (Solaris/AIX) 可以结合 vi 使用 here 构造:
vi file 2>&1 >/dev/null <@
1,$ s/pattern/replacement/g
:wq
@
我不喜欢 vi 解决方案。当您的模式具有 / 或其他特殊字符时,将很难调试出了什么问题。当 replacement
由 shell 变量给出时,您可能需要先检查内容。
您可以很容易地复制 Perl 使用 -i
开关所做的事情。
{
local ($^I, @ARGV) = ("", 'file');
while (<>) { s/foo/bar/; print; }
}
您可以试试下面的简单方法。看看它是否最符合您的要求。
use strict;
use warnings;
# Get file to process
my ($file, $pattern, $replacement) = @ARGV;
# Read file
open my $FH, "<", $file or die "Unable to open $file for read exited $? $!";
chomp (my @lines = <$FH>);
close $FH;
# Parse and replace text in same file
open $FH, ">", $file or die "Unable to open $file for write exited $? $!";
for (@lines){
print {$FH} $_ if (s/$pattern/$replacement/g);
}
close $FH;
1;
file.txt:
Hi Java, This is Java Programming.
执行:
D:\swadhi\perl>perl module.pl file.txt Java Source
file.txt
Hi Source, This is Source Programming.
您可以处理问题中的用例,而无需重新创建 -i
标志的功能或创建一次性变量。将标志添加到 Perl 脚本的 shebang 并读取 STDIN:
#!/usr/bin/env perl -i
while (<>) {
s/pattern/replacement/g;
print;
}
用法:保存脚本,使其可执行(使用 chmod +x
),以及 运行
path/to/the/regex-script test.txt
(或 regex-script test.txt
如果脚本保存到 $PATH 中的目录。)
超越问题:
如果你需要运行多次顺序替换,那就是
#!/usr/bin/env perl -i
while (<>) {
s/pattern/replacement/g;
s/pattern2/replacement2/g;
print;
}
如问题示例,源文件将不会被备份。就像在 -e
oneliner 中一样,您可以通过向 -i
标志添加 backupExtension 来备份到 file.<backupExtension>
。例如,
#!/usr/bin/env perl -i.bak