좋아, 내가 그랬다고 가정해보자파일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
대체 문자열을 저장합니다.