さて、私はそうだったとしましょう。ファイルA.txt以下が含まれます:
string1, 3269
asdf, 8635
ghjk, 8534
foo, 4179
bar, 23490
以下を保存できる1つまたは2つのテキストファイル(どちらも簡単なファイル)を使用したいと思います。
ファイル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番目のフィールド値を配列$3
としてキャプチャします。a
$1
next
- 次のレコードに移動
$1 in a
- 2番目の入力ファイル(例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
警告:同じ検索パターンが複数回発生した場合は、最後のパターンのみが保存され使用されます。この制限を回避する最も簡単な方法は、検索パターンと対応する置換項目を2つの別々の配列に保存することです。
#!/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
}
このバージョンではハッシュは必要ないので、2つの配列を使用しました。
@srch
検索パターンを保存し、@reps
代替文字列を保存します。