使用正则表达式查找和替换文件

使用正则表达式查找和替换文件

好吧,假设我有文件A.txt包含这个:

string1, 3269
asdf, 8635
ghjk, 8534
foo, 4179
bar, 23490

我想使用一个或两个文本文件(无论哪种情况都更容易),我可以在其中存储以下内容:

文件B.txt

string1 | 1string
bar | foo

|”将是一个分隔符,如果它必须是另一个文件也没关系(1string和foo将在文件C.txt如果是这样的话)。

我想使用要搜索和替换的字符串运行搜索和替换操作文件B.txt(并且可能是文件C.txt),因此结果如下:

1string, 3269
asdf, 8635
ghjk, 8534
foo, 4179
foo, 23490

我可以使用任何工具来执行此操作吗?谢谢!

答案1

Awk解决方案:

awk 'NR==FNR{ a[$1]=$3; next }$1 in a{ $1=a[$1] }1' FileB.txt FS=',' OFS=',' FileA.txt
  • NR==FNR{ ... }- 处理第一个输入文件,即FileB.txt
    • a[$1]=$3-使用第一个字段作为数组索引/键将每个第三个字段值捕获$3到数组中a$1
    • next- 跳转到下一条记录
  • $1 in a- 在处理第二个输入文件(即FileA.txt)时,检查第一个字段值是否$1出现在数组a键中:
    • $1=a[$1]- 用重置值替换

输出:

1string,  3269
asdf, 8635
ghjk, 8534
foo, 4179
foo,  23490

答案2

使用perl, 并预编译正则表达式以提高效率(对于只有 2 个搜索和替换模式来说并不是非常重要,但如果有数百或数千个则非常有用):

#!/usr/bin/perl

use strict;

my %rep=();  # hash for storing search patterns with their replacements
my @rep=();  # array for storing search patterns in the order they were seen.

# first arg is the replacement file
my $replacements_file = shift;

open(REP,'<',$replacements_file) || die "Couldn't open $replacements_file: $!\n";
while(<REP>) {
  chomp;
  my ($s, $r) = split / \| /;

  my $search = qr/$s/; # precompile the regex

  $rep{$search} = $r;  # store the search regex and its replacement in a hash

  push @rep, $search;  # use an indexed array to remember the order the patterns
                       # were read in.
};
close(REP);

# main loop: process remaining args and/or stdin, apply each
# search and replace to every input line.

while(<>) {

  foreach my $s (@rep) {
    s/$s/$rep{$s}/;
  };

  print
}

示例输出:

$ ./replace.pl FileB.txt FileA.txt 
1string, 3269
asdf, 8635
ghjk, 8534
foo, 4179
foo, 23490

警告:如果完全相同的搜索模式出现多次,则仅存储和使用最后一个。避免该限制的最简单方法是将搜索模式及其相应的替换存储在两个单独的数组中:

#!/usr/bin/perl

use strict;

my (@srch, @reps)=();

my $replacements_file = shift;

open(REP,'<',$replacements_file) || die "Couldn't open $replacements_file: $!\n";
my $count=0;
while(<REP>) {
  chomp;
  my ($s, $r) = split / \| /;

  $srch[$count] = qr/$s/;
  $reps[$count] = $r;
  $count++;
};
close(REP);
$count--;

while(<>) {
  foreach my $i (0..$count) {
    s/$srch[$i]/$reps[$i]/;
  };
  print
}

此版本中不需要哈希,因此我使用了两个数组。 @srch保存搜索模式并@reps保存替换字符串。

相关内容