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 변수가 잘 설명되지 않는다는 점이라고 생각합니다. 나는 이중 단순 따옴표를 사용해 보았습니다. 또한 다양한 제안을 시도했지만 아무것도 작동하지 않는 것 같습니다!

답변1

이렇게 할 수도 있지만:

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

껍질이 있다는 뜻이죠확장$pawk이는 나쁜 습관이며 기본적으로 명령 주입 취약점에 해당합니다(예: $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

관련 정보