awk의 동적 정규 표현식

Nov 22 2020

다음과 같은 텍스트 파일이 있습니다.

1.txt

AA;00000;
BB;11111;
GG;22222;

2.txt

KK;WW;55555;11111;
KK;FF;ZZ;11111;
KK;RR;YY;11111;

3.txt 출력을 생성합니다.

AA;00000;
BB;11111;KK;WW;55555;FF;ZZ;RR;YY
GG;22222;

이 .awk 스크립트로 (Windows에서 cmd와 함께 사용)

#!/usr/bin/awk -f 

NR != FNR {
    exit
}
{
    printf "%s", $0 } /^BB/ { o = "" while (getline tmp < ARGV[2]) { n = split (tmp,arr,";") for (i=1; i<=n; i++) if(!match($0,arr[i]) && !match(o,arr[i]))
                o=o arr[i]";"
    }
    printf "%s", o
}
{
    print ""
}

사용법은 awk -f script.awk 1.txt 2.txt

괜찮은 것 같지만이 상황을 고려하십시오

1.txt

AA;BB;

2.txt

CC;DD;BB;AA;

이제 이런 식으로 교체

AA로 교체 d(2)
BB로 대체 http://a.o/f/i.p?t=1
CC로 대체 Link
DDA_x-y.7z

스크립트는 3.txt를 생성 할 수 없습니다.

AA;BB;CC;DD;

또는 대체 된 텍스트를 사용하면이 3.txt 텍스트 출력을 생성 할 수 없습니다.

   d(2);http://a.o/f/i.p?t=1;Link;A_x-y.7z;

스크립트가 그런 방식으로 작동하기 때문에 AA, 같은 중복 필드 BB가 3.txt 출력에서 ​​제거 된 것을 볼 수 있습니다 .

나는 그것이이 함께 할 수있다 생각 (...)에 그룹화 정규식으로 간주되는 match()첫 번째 매개 변수는 정규식으로하고 전달하여 $0동적 정규 표현식에서 * 모두 "로 처리됩니다 O를 awk말하다

답변

1 EdMorton Nov 22 2020 at 23:36
$ cat tst.awk BEGIN { FS=OFS=";" } { key = $(NF-1) }
NR == FNR {
    for (i=1; i<(NF-1); i++) {
        if ( !seen[key,$i]++ ) { map[key] = (key in map ? map[key] OFS : "") $i
        }
    }
    next
}
{ print $0 map[key] }

$ awk -f tst.awk 2.txt 1.txt
AA;00000;
BB;11111;KK;WW;55555;FF;ZZ;RR;YY
GG;22222;

위의 내용은 배열 인덱스의 해시 조회에서 리터럴 문자열을 사용하므로 입력에 어떤 문자가 있는지는 신경 쓰지 않습니다. 당신이 리터럴 문자열은 다음 정규 표현식 함수 또는 연산자를 (예를 들어, 사용하지 않는 사용자의 입력을 처리하려면 match(), ~, sub()그것에), 단지 사용 문자열 함수 / 연산자를 (예를 들어 index(), ==, substr(), in).