awk eine Variable als regulären Ausdruck

awk eine Variable als regulären Ausdruck

Die Frage ist wirklich einfach, ich habe alle Fragen gelesen und schaffe es immer noch nicht! Ich habe eine einfache Datei wie diese

$cat file1.txt
ALA
AJD
KSF

Und ich möchte, dass awk jeden der Werte als regulären Ausdruck verwendet, um Zeilen aus einer anderen Datei in eine andere zu drucken:

$cat file2.txt
name,st,ed,le
ALA,10,12,12
ALA,2,5,4
ALA,6,5,8
AJD,5,8,7
KSF,5,8,7

Mein Skript ist also

while read p;
awk -F"," 'NR==1{print $0}' file2.txt > $p.csv
awk -F"," '/$p/{print $0}' file2.txt >> $p.csv
done <file1.txt

Und die gewünschte Ausgabe wäre:

$cat ALA.csv
name,st,ed,le
ALA,10,12,12
ALA,2,5,4
ALA,6,5,8
$cat AJD.csv
name,st,ed,le
AJD,5,8,7
$cat KSF.csv
name,st,ed,le
KSF,5,8,7

Leider bekomme ich in jeder Datei nur die Kopfzeilen ausgedruckt. Ich habe jeden Wert aus file1.txt manuell durch $p ersetzt und es funktioniert einwandfrei. Ich denke also, das Problem liegt darin, dass die Variable $p nicht richtig interpretiert wird. Ich habe es mit Anführungszeichen versucht, doppelt einfach. Ich habe auch viele verschiedene Vorschläge ausprobiert, die ich gefunden habe, aber nichts scheint zu funktionieren!

Antwort1

Sie könnten Folgendes tun:

awk "/$p/" Datei2.txt > "$p.csv"

Das heißt, die Schaleexpandierender Inhalt der $pShell-Variable im Code, der an übergeben wird awk, ist eine schlechte Praxis und läuft im Grunde auf eine Schwachstelle bei der Befehlseinschleusung hinaus (beispielsweise für einen Wert $pwie ^/{system("reboot");/). Am besten ist es, die Shell-Variable so wie sie ist an awk zu übergeben und ~den Operator von awk für die Regexp-Übereinstimmung zu verwenden. Der beste Weg ist über eine Umgebungsvariable und awkein ENVIRONspezielles Array von :

export P
while IFS= read -r P; do
  awk 'NR == 1 || $0 ~ ENVIRON["P"]' < file2.txt > "$P.csv"
done < file1.txt

Hier könnten Sie jedoch die Shell-Schleife vermeiden und nur einen Durchlauf durch die Dateien durchführen:

awk 'NR == FNR {files[$0]; next}
     FNR == 1 {for (f in files) print > f ".csv"; next}
     {
       for (f in files)
         if ($0 ~ f) print > f ".csv"
     }' file1.txt file2.txt

verwandte Informationen