질문은 정말 간단해요. 다 읽었는데 아직도 못해요! 다음과 같은 일반 파일이 있습니다.
$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"
껍질이 있다는 뜻이죠확장$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