问题真的很简单,我都看完了,还是做不到!我有一个像这样的普通文件
$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
传递给 的代码中 shell 变量的内容awk
,这是不好的做法,基本上相当于命令注入漏洞(例如,对于$p
like的值^/{system("reboot");/
)。最好的方法是将 shell 变量按原样传递给 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
但在这里,您可以避免 shell 循环,只在文件中执行一次:
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