Awk'de dinamik normal ifadeler

Nov 22 2020

Gibi metin dosyalarım var

1.txt

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

2.txt

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

Bu 3.txt çıktısını oluşturuyorum

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

bu .awk komut dosyasıyla (Windows'ta cmd ile kullanıyorum)

#!/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 ""
}

Kullanım awk -f script.awk 1.txt 2.txt

İyi görünüyor ama bu durumu düşünün

1.txt

AA;BB;

2.txt

CC;DD;BB;AA;

şimdi bu şekilde değiştirin

AAile değiştirilir d(2)
BBdeğiştirilir http://a.o/f/i.p?t=1
CCdeğiştirilir Link
DDileA_x-y.7z

komut dosyası 3.txt oluşturamaz

AA;BB;CC;DD;

veya değiştirilen metni kullanarak bu 3.txt metin çıktısını oluşturamaz

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

Sen alanlar gibi o çiftleri görebilirsiniz AA, BBsenaryo bu şekilde çalıştığı için 3.txt çıkışı kaldırılır.

Ben ilgisi yoktur şüpheli (...)gruplaması REGEX olarak atılıyor match()birinci parametresi bir REGEX olduğu gibi ve geçirerek $0ve Dinamik Düzenli İfadeler içinde * hem" olarak ele alınacaktır o awkkonuşmak

Yanıtlar

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;

Yukarıdakiler, dizi indekslerinin karma aramasında değişmez dizeleri kullanır, bu nedenle girişinizde hangi karakterlerin olduğu umurunda değildir. Eğer edebi dizeleri sonra regexp işlevleri veya operatörleri (örneğin kullanmayın olarak girdi tedavi olmak istiyorsanız match(), ~, sub()bunun üzerine), sadece kullanım dize işlevleri / operatörler (örneğin index(), ==, substr(), in).