首页 > 解决方案 > 如何从另一个 csv 文件的选定列动态创建新的 csv?

问题描述

我动态地遍历一个 csv 文件并选择符合我需要的标准的列。我的 CSV 用逗号分隔。我将这些索引保存到一个看起来像的数组中

echo "${cols_needed[@]}"

1 3 4 7 8

然后我需要将这些列写入一个新文件,并且我尝试了以下 cut 和 awk 命令,但是,由于数组是动态创建的,我似乎无法找到可以一次选择它们的正确命令。我尝试过剪切、awk 和粘贴命令。

awk -v fields=${cols_needed[@]} 'BEGIN{ n = split(fields,f) }
    { for (i=1; i<=n; ++i) printf "%s%s", $f[i], (i<n?OFS:ORS) }' test.csv

这会引发错误,因为它无法拆分字段,除非我对它们进行硬编码(即使那样,它也只能执行 2),拆分空格。

fields="1 2’

我试图动态创建 -f 参数,但只能像这样在循环中使用一个变量

for item in "${cols_needed[@]}";
    do
       cat test.csv | cut -f$item
    done

一次输出一列。

我试图用逗号动态创建它 - 输入为 1,3,4,7...

cat test.csv | cut -f${cols_needed[@]};

这也行不通!

任何帮助表示赞赏!我知道 awk 不像 bash 那样工作,我们不能以同样的方式传递变量。我觉得我有点绕圈子!提前致谢。

标签: bashawkcut

解决方案


假设你在 bash 中有这个变量:

$ echo "${cols_needed[@]}"
3 4 7 8

这个 CSV 文件:

$ cat file.csv
1,2,3,4,5,6,7,8
11,12,13,14,15,16,17,18
21,22,23,24,25,26,27,28

您可以通过这种方式在 awk 中选择该 csv 文件的列:

awk  '
BEGIN{FS=OFS=","}
FNR==NR{split($0, cols," "); next}
{
    s=""
    for (e=1;e<=length(cols); e++) 
           s=e<length(cols) ? s $(cols[e]) OFS : s $(cols[e])
    print s
}' <(echo "${cols_needed[@]}") file.csv

印刷:

3,4,7,8
13,14,17,18
23,24,27,28

或者,您可以这样做:

awk -v cw="${cols_needed[*]}" '
BEGIN{FS=OFS=","; split(cw, cols," ")}
{
    s=""
    for (e=1;e<=length(cols); e++) 
           s=e<length(cols) ? s $(cols[e]) OFS : s $(cols[e])
    print s
}' file.csv 
# same output

顺便说一句,你可以完全做到这一点cut

cut -d ',' -f $(IFS=, ; echo "${cols_needed[*]}") file.csv
3,4,7,8
13,14,17,18
23,24,27,28

推荐阅读