使用 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}]