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"

那就是有壳扩张$p传递给 的代码中 shell 变量的内容awk,这是不好的做法,基本上相当于命令注入漏洞(例如,对于$plike的值^/{system("reboot");/)。最好的方法是将 shell 变量按原样传递给 awk 并使用 awk 的~运算符进行正则表达式匹配。最好的方法是通过环境变量 和awkENVIRON特殊数组:

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

相关内容