awk переменная как регулярное выражение

awk переменная как регулярное выражение

Вопрос очень простой, я прочитал все вопросы и все равно не могу сделать! У меня есть простой файл, такой как этот

$cat file1.txt
ALA
AJD
KSF

И я хочу, чтобы awk использовал каждое из значений как регулярное выражение для печати строк из одного файла в другой:

$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

Итак, мой сценарий:

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

И желаемый результат будет таким:

$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

К сожалению, я получаю только заголовки, напечатанные в каждом файле. Я вручную подставил каждое значение из file1.txt, заменив $p, и это работает отлично. Поэтому я думаю, что проблема в том, что переменная $p не была правильно интерпретирована. Я пробовал с кавычками, double simple. Я также пробовал много разных предложений, которые нашел, но ничего не работает!

решение1

Хотя вы могли бы сделать:

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

То есть иметь оболочкурасширятьсодержимое $pпеременной оболочки в коде, переданном в awk, это плохая практика и по сути равносильно уязвимости инъекции команд (например, для значения типа $p) ^/{system("reboot");/. Лучше всего передать переменную оболочки как есть в awk и использовать ~оператор awk для сопоставления регулярных выражений. Лучший способ — через переменную окружения и awkспециальный ENVIRONмассив :

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

Но здесь можно избежать цикла оболочки и выполнить только один проход по файлам:

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

Связанный контент