使用 perl 搜索和替换文件中的某些文本部分
search and replace some portion of text in a file using perl
我编写了一个 perl 脚本来用其他文本替换文件中的文本,同时保留部分搜索文本。
但是,我的脚本没有按预期工作,我在 Whosebug 中看到了类似的问题并遵循了建议,但脚本仍然没有给出预期的输出。
请查看我希望在文件中替换的以下文本(突出显示)和编写的相应脚本
在文件中,我想用“150”替换十进制值。
任何帮助将不胜感激。感谢您的宝贵时间!
#!usr/bin/perl
2
3 use strict;
4 use warnings;
5
6 my $filename = 'input_file.txt';
7
8 my $data = read_file($filename);
9 $data =~ s/(g_clk.*-multiply_by\s\+)\d\+/ 150/ge;
10 print "$data\n";
11 write_file($filename, $data);
12 exit;
13
14 sub read_file {
15 my ($filename) = @_;
16
17 open my $in, '<:encoding(UTF-8)', $filename or die "Could not open '$filename' for reading $!";
18 local $/ = undef;
19 my $all = <$in>;
20 close $in;
21
22 return $all;
23 }
24
25 sub write_file {
26 my ($filename, $content) = @_;
27
28 open my $out, '>:encoding(UTF-8)', $filename or die "Could not open '$filename' for writing $!";;
29 print $out $content;
30 close $out;
31
32 return;
33 }
按此更改正则表达式:
$data =~ s/(-multiply_by\s+)\d+/ 150/g;
它匹配“-multiply_by
”和空格 (\s+
) 后跟 1 个或多个数字 (\d+
)。使用括号来记住文本(在 </code> 中)。这在第二部分(替换部分)很有用</p>
<p><strong>更新 1</strong>:要替换具体部分(由行号分隔),最好逐行读取文件,然后使用 $.在需要时应用正则表达式的特殊变量。示例:</p>
<pre><code>open my $in, '<:encoding(UTF-8)', $filename_in or die $!;
open my $out, '<:encoding(UTF-8)', $filename_out or die $!;
while( my $data = <$in> ) {
if( $. >= 4 && $. <= 12) {
# Replace only if line number ($.) is between 4 and 12
$data =~ s/(-multiply_by\s+)\d+/ 150/g;
}
# Print at output the handled line
print $out $data;
}
close $in;
close $out;
更新 2:要替换具体部分(由同一行的其他值分隔),按如下方式搜索您的条件:
open my $in, '<:encoding(UTF-8)', $filename_in or die $!;
open my $out, '<:encoding(UTF-8)', $filename_out or die $!;
while( my $data = <$in> ) {
if( $data =~ /-name glck / ) {
# Replace only if line has "-name glck" text
$data =~ s/(-multiply_by\s+)\d+/ 150/g;
}
# Print at output the handled line
print $out $data;
}
close $in;
close $out;
据我所知,你的正则表达式中有一个致命错误。
$data =~ s/(g_clk.*-multiply_by\s\+)\d\+/ 150/ge;
# ^^ ^^
你对加号+
进行了转义,这使得它失去了作为量词的特殊含义,现在只是表示“匹配一个字面加号”。
如果您删除加号前的反斜杠,它应该可以工作。
但是,这不是您犯的唯一错误。
- 您使用
/g
全局修饰符,即使您确实不想每行匹配多次。
- 您使用了
/e
eval 修饰符,即使您确实不想将替换部分作为 Perl 代码求值。
至于有问题的设计选择:
- 你将文件放入一个变量而不是逐行读取,即使你真的只想每行匹配一次(这可能是你使用
/g
全局修饰符的原因)
- 您在
print "$data\n";
行中添加了一个额外的换行符。
- 您以
exit
结束程序,即使程序会在可执行代码结束时自然退出。
- 如果您仍然想要 slurp 文件,最好使用已经发明的模块
File::Slurp
而不是重新发明轮子。
此外,这可以用“所谓的”单线解决。这是 Perl 的核心功能,即就地编辑文件。你可以摆脱这样简单的事情:
perl -pe's/g_clk.*-multiply_by \K\d+/150/' input.txt > output.txt
这将写入一个新文件,使用 shell 重定向输出。您还可以使用 -i
开关就地编辑文件:
perl -pi.bak -e's/g_clk.*-multiply_by \K\d+/150/' input.txt
这将以 .bak
扩展名保存原始文件。不过要小心,因为 运行 命令两次仍会覆盖您的原始文件。最好的选择是在尝试就地编辑之前保存永久备份。
这种风格的程序是这种程序的简短版本(不包括就地编辑)
while (<>) {
s/g_clk.*-multiply_by \K\d+/150/;
print;
}
以下代码演示了众多方法中的一种
use strict;
use warnings;
use feature 'say';
my $re = qr/^create_gene_clk .*? g_clk .*? -multiply_by \K\d+/;
my $mul = 150;
while( <DATA> ) {
chomp;
s/$re/$mul/;
say;
}
__DATA__
create_gene_clk -name dft_clk -source [get_pins (5201/C)] -multiply_by 104 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name dft_clk -source [get_pins (5201/C)] -multiply_by 204 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name dft_clk -source [get_pins (5201/C)] -multiply_by 324 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/C)] -multiply_by 14 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/D)] -multiply_by 104 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/E)] -multiply_by 114 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/R)] -multiply_by 001 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/T)] -multiply_by 154 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/Y)] -multiply_by 182 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/U)] -multiply_by 194 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/C)] -multiply_by 004 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/C)] -multiply_by 104 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name bgclk -source [get_pins (5201/U)] -multiply_by 104 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name bgclk -source [get_pins (5201/C)] -multiply_by 104 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name bgclk -source [get_pins (5201/C)] -multiply_by 104 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
输出
create_gene_clk -name dft_clk -source [get_pins (5201/C)] -multiply_by 104 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name dft_clk -source [get_pins (5201/C)] -multiply_by 204 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name dft_clk -source [get_pins (5201/C)] -multiply_by 324 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/C)] -multiply_by 150 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/D)] -multiply_by 150 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/E)] -multiply_by 150 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/R)] -multiply_by 150 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/T)] -multiply_by 150 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/Y)] -multiply_by 150 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/U)] -multiply_by 150 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/C)] -multiply_by 150 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/C)] -multiply_by 150 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name bgclk -source [get_pins (5201/U)] -multiply_by 104 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name bgclk -source [get_pins (5201/C)] -multiply_by 104 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name bgclk -source [get_pins (5201/C)] -multiply_by 104 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
我编写了一个 perl 脚本来用其他文本替换文件中的文本,同时保留部分搜索文本。
但是,我的脚本没有按预期工作,我在 Whosebug 中看到了类似的问题并遵循了建议,但脚本仍然没有给出预期的输出。
请查看我希望在文件中替换的以下文本(突出显示)和编写的相应脚本
在文件中,我想用“150”替换十进制值。 任何帮助将不胜感激。感谢您的宝贵时间!
#!usr/bin/perl
2
3 use strict;
4 use warnings;
5
6 my $filename = 'input_file.txt';
7
8 my $data = read_file($filename);
9 $data =~ s/(g_clk.*-multiply_by\s\+)\d\+/ 150/ge;
10 print "$data\n";
11 write_file($filename, $data);
12 exit;
13
14 sub read_file {
15 my ($filename) = @_;
16
17 open my $in, '<:encoding(UTF-8)', $filename or die "Could not open '$filename' for reading $!";
18 local $/ = undef;
19 my $all = <$in>;
20 close $in;
21
22 return $all;
23 }
24
25 sub write_file {
26 my ($filename, $content) = @_;
27
28 open my $out, '>:encoding(UTF-8)', $filename or die "Could not open '$filename' for writing $!";;
29 print $out $content;
30 close $out;
31
32 return;
33 }
按此更改正则表达式:
$data =~ s/(-multiply_by\s+)\d+/ 150/g;
它匹配“-multiply_by
”和空格 (\s+
) 后跟 1 个或多个数字 (\d+
)。使用括号来记住文本(在 </code> 中)。这在第二部分(替换部分)很有用</p>
<p><strong>更新 1</strong>:要替换具体部分(由行号分隔),最好逐行读取文件,然后使用 $.在需要时应用正则表达式的特殊变量。示例:</p>
<pre><code>open my $in, '<:encoding(UTF-8)', $filename_in or die $!;
open my $out, '<:encoding(UTF-8)', $filename_out or die $!;
while( my $data = <$in> ) {
if( $. >= 4 && $. <= 12) {
# Replace only if line number ($.) is between 4 and 12
$data =~ s/(-multiply_by\s+)\d+/ 150/g;
}
# Print at output the handled line
print $out $data;
}
close $in;
close $out;
更新 2:要替换具体部分(由同一行的其他值分隔),按如下方式搜索您的条件:
open my $in, '<:encoding(UTF-8)', $filename_in or die $!;
open my $out, '<:encoding(UTF-8)', $filename_out or die $!;
while( my $data = <$in> ) {
if( $data =~ /-name glck / ) {
# Replace only if line has "-name glck" text
$data =~ s/(-multiply_by\s+)\d+/ 150/g;
}
# Print at output the handled line
print $out $data;
}
close $in;
close $out;
据我所知,你的正则表达式中有一个致命错误。
$data =~ s/(g_clk.*-multiply_by\s\+)\d\+/ 150/ge;
# ^^ ^^
你对加号+
进行了转义,这使得它失去了作为量词的特殊含义,现在只是表示“匹配一个字面加号”。
如果您删除加号前的反斜杠,它应该可以工作。
但是,这不是您犯的唯一错误。
- 您使用
/g
全局修饰符,即使您确实不想每行匹配多次。 - 您使用了
/e
eval 修饰符,即使您确实不想将替换部分作为 Perl 代码求值。
至于有问题的设计选择:
- 你将文件放入一个变量而不是逐行读取,即使你真的只想每行匹配一次(这可能是你使用
/g
全局修饰符的原因) - 您在
print "$data\n";
行中添加了一个额外的换行符。 - 您以
exit
结束程序,即使程序会在可执行代码结束时自然退出。 - 如果您仍然想要 slurp 文件,最好使用已经发明的模块
File::Slurp
而不是重新发明轮子。
此外,这可以用“所谓的”单线解决。这是 Perl 的核心功能,即就地编辑文件。你可以摆脱这样简单的事情:
perl -pe's/g_clk.*-multiply_by \K\d+/150/' input.txt > output.txt
这将写入一个新文件,使用 shell 重定向输出。您还可以使用 -i
开关就地编辑文件:
perl -pi.bak -e's/g_clk.*-multiply_by \K\d+/150/' input.txt
这将以 .bak
扩展名保存原始文件。不过要小心,因为 运行 命令两次仍会覆盖您的原始文件。最好的选择是在尝试就地编辑之前保存永久备份。
这种风格的程序是这种程序的简短版本(不包括就地编辑)
while (<>) {
s/g_clk.*-multiply_by \K\d+/150/;
print;
}
以下代码演示了众多方法中的一种
use strict;
use warnings;
use feature 'say';
my $re = qr/^create_gene_clk .*? g_clk .*? -multiply_by \K\d+/;
my $mul = 150;
while( <DATA> ) {
chomp;
s/$re/$mul/;
say;
}
__DATA__
create_gene_clk -name dft_clk -source [get_pins (5201/C)] -multiply_by 104 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name dft_clk -source [get_pins (5201/C)] -multiply_by 204 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name dft_clk -source [get_pins (5201/C)] -multiply_by 324 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/C)] -multiply_by 14 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/D)] -multiply_by 104 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/E)] -multiply_by 114 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/R)] -multiply_by 001 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/T)] -multiply_by 154 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/Y)] -multiply_by 182 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/U)] -multiply_by 194 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/C)] -multiply_by 004 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/C)] -multiply_by 104 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name bgclk -source [get_pins (5201/U)] -multiply_by 104 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name bgclk -source [get_pins (5201/C)] -multiply_by 104 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name bgclk -source [get_pins (5201/C)] -multiply_by 104 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
输出
create_gene_clk -name dft_clk -source [get_pins (5201/C)] -multiply_by 104 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name dft_clk -source [get_pins (5201/C)] -multiply_by 204 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name dft_clk -source [get_pins (5201/C)] -multiply_by 324 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/C)] -multiply_by 150 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/D)] -multiply_by 150 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/E)] -multiply_by 150 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/R)] -multiply_by 150 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/T)] -multiply_by 150 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/Y)] -multiply_by 150 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/U)] -multiply_by 150 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/C)] -multiply_by 150 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name g_clk -source [get_pins (5201/C)] -multiply_by 150 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name bgclk -source [get_pins (5201/U)] -multiply_by 104 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name bgclk -source [get_pins (5201/C)] -multiply_by 104 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]
create_gene_clk -name bgclk -source [get_pins (5201/C)] -multiply_by 104 -add -master_clk [get_clk {fin}] [get_p {pll/clk/out}]