搜索并替换文件中的字符串

时间:2019-09-01 20:15:11

标签: perl

我正在尝试从输入文件中读取内容,仅从文件中复制某些代码行,然后在输出文件中打印。

某些代码行取决于:

  1. 确定第一行的代码名称(IP1_NAME或IP2_NAME)
  2. 确定最后一行(END_OF_LIST)的模式

输入文件:

IP1_NAME    
   /ip1name/ip1dir/ //CLIENT_NAME/ip1name/ip1dir
   /ip1testname/ip1testdir/ //CLIENT_NAME/ip1testname/ip1testdir
END_OF_LIST
IP2_NAME
   /ip2name/ip2dir/ //CLIENT_NAME/ip2name/ip2dir
   /ip2testname/ip2testdir/ //CLIENT_NAME/ip2testname/ip2testdir
END_OF_LIST

输出文件:

(如果选择了IP1_NAME,并且应该用tester_ip替换CLIENT_NAME)

/ip1name/ip1dir/ //tester_ip/ip1name/ip1dir
/ip1testname/ip1testdir/ //tester_ip/ip1testname/ip1testdir

3 个答案:

答案 0 :(得分:1)

您可以使用以下单线来抽出两种模式之间的界线:

perl -0777 -ne 'print "$1\n" while /IP1_NAME(.*?)END_OF_LIST/gs' in.txt > out.txt

其中in.txt是输入文件,out.txt是输出文件。

此用例实际上在perlfaq6: Regular Expressions中有所描述。

然后,您可以修改输出文件,以将CLIENT_NAME替换为tester_ip

perl -pi -e 's/CLIENT_NAME/tester_ip/' y.txt

答案 1 :(得分:1)

使用标量range operator作为脚本而不是单行代码:

#/usr/bin/env perl
use warnings;
use strict;
use autodie;
use feature qw/say/;

process('input.txt', qr/^IP1_NAME$/, qr/^END_OF_LIST$/, 'tester_ip');

sub process {
  my ($filename, $startpat, $endpat, $newip) = @_;
  open my $file, '<', $filename;
  while (my $line = <$file>) {
    chomp $line;
    if ($line =~ /$startpat/ .. $line =~ /$endpat/) {
      next unless $line =~ /^\s/; # Skip the start and lines.
      $line =~ s/^\s+//; # Remove indentation
      $line =~ s/CLIENT_NAME/$newip/g; # Replace with desired value
      say $line;
    }
  }
}

在示例输入文件上运行此命令会产生:

/ip1name/ip1dir/ //tester_ip/ip1name/ip1dir
/ip1testname/ip1testdir/ //tester_ip/ip1testname/ip1testdir

答案 2 :(得分:1)

我假设您的输入文件中还有其他内容,否则我们就不必像上面那样用这些开始和结束标记跳过循环了,我们可以说

perl -ne "print if /^ /"

那真是愚蠢,对;-)

因此,正如我在评论中所述,触发器存在潜在的问题。而且,尽管它很聪明,但在可读性或冗长性(冗长性)方面并不能给您带来多少好处,因为无论如何您都必须再次进行测试以免处理标记线。

只要没有排他性触发器运算符,我就会寻求更可靠的解决方案。

my $in;

while (<DATA>) {
    $in = 1, next if /^IP\d_NAME/;
    $in = 0       if /^END_OF_LIST/;

    if ( $in )
    {
        s/CLIENT_NAME/tester_ip/;
        print;
    }
}
__DATA__
cruft
IP1_NAME    
   /ip1name/ip1dir/ //CLIENT_NAME/ip1name/ip1dir
   /ip1testname/ip1testdir/ //CLIENT_NAME/ip1testname/ip1testdir
END_OF_LIST
more
cruft
IP2_NAME
   /ip2name/ip2dir/ //CLIENT_NAME/ip2name/ip2dir
   /ip2testname/ip2testdir/ //CLIENT_NAME/ip2testname/ip2testdir
END_OF_LIST
Lore Ipsargh!
相关问题