【问题标题】:Multiple pattern match and replace多个模式匹配和替换
【发布时间】:2015-06-30 09:34:49
【问题描述】:

如何从文件中提取模式并用文件中的新模式替换多个模式? 例如: 假设模式文件是 pattern.txt,如下 2,000 行。

a  
b   
d  
e  
f  
....  
...  
...  

要替换模式的文件是 replace.txt,其中包含:

a,1    
b,3  
c,5  
d,10  
e,14   
....  
...  
...   

文件 patterns.txt 的预期最终文件内容是:

a,1    
b,3    
d,10  
e,14  
....  
...  
... 

【问题讨论】:

  • 这是正确的 csv 吗?是否可以包含引号和空格以及奇数字符,例如"foo bar", "a,b,c,d", "äåäö"
  • 是的,它是一个正确的 csv 文件

标签: regex perl awk sed grep


【解决方案1】:

命令行中的 Perl,

perl -i -pe'
  BEGIN{ local (@ARGV, $/, $^I) =pop; %h = split /[\s,]+/, <> }
  s| (\S+)\K |,$h{$1}|x
' pattern.txt replace.txt

它会读取第二个文件的内容($/ 到 undef),并暂时禁用就地编辑($^I 到 undef),在空格/逗号上拆分字符串并在键/值中填充 %h 哈希方式。然后为第一个文件的每一行添加当前键的逗号和值。

【讨论】:

  • (\w+) 对于 foo bar?query=foo&amp;bar=baz 等行将失败
  • 比我整理的要简洁得多。虽然我认为这并不总是一件好事......
  • @Sobrique 是的,这是真的。
  • @TLP 我指的是原始输入。
  • 嗯,对我来说,原始输入看起来像是占位符。据我们所知,它是任意字符串。
【解决方案2】:

由于您的输入中可能包含任意字符,因此使用Text::CSV 可能是最安全的。好处是它可以处理带引号的分隔符、多行字符串等。缺点是它可能会破坏非 csv 内容,因此它有点依赖于您的输入是否是正确的 csv。

use strict;
use warnings;
use Text::CSV;

my $csv = Text::CSV->new({
        binary => 1,
        eol => $/,
    });
my %s;
my ($input, $replace) = @ARGV;
open my $fh, "<", $replace or die "Cannot open $replace: $!";
while (my $row = $csv->getline($fh)) {
    my ($key, $line) = @$row;
    $s{$key} = $line;
}

open $fh, "<", $input or die "Cannot open $input: $!";
while (<$fh>) {
    chomp;
    $csv->print(*STDOUT, [$_, $s{$_}]);
}

【讨论】:

    【解决方案3】:

    不确定这是否真的需要一个正则表达式,因为您并没有真正改变您的来源,就像“只是”基于关键字段的打印一样。

    所以我会这样处理它:

    #!/usr/bin/env perl
    use strict;
    use warnings;
    
    open( my $replace, "<", "replace.txt" ) or die $!;
    
    my %replacements;
    while (<$replace>) {
        chomp;
        my ( $key, $value ) = split(/,/);
        $replacements{$key} = $value;
    }
    close($replace);
    
    open( my $input,  "<", "input.txt" )    or die $!;
    open( my $output, ">", "patterns.txt" ) or die $!;
    
    while ( my $line = <$input> ) {
        chomp $line;
        if ( $replacements{$line} ) {
            print {$output} $replacements{$line}, "\n";
        }
    }
    
    close($input);
    close($output);
    

    它不像其他一些示例那样简洁,但希望更清楚它实际上在做什么。这我称之为好事。 (我可以让它更紧凑,就像perl 是(不)著名的那样)。

    【讨论】:

      猜你喜欢
      • 2021-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-26
      • 1970-01-01
      相关资源
      最近更新 更多