質問は本当に簡単です。全部読んだけどまだできません!次の一般的なファイルがあります。
$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