정규식을 사용하여 파일 찾기 및 바꾸기

정규식을 사용하여 파일 찾기 및 바꾸기

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

관련 정보