Unix shell脚本根据另一个csv文件的头选择csv文件中的列

cczfrluj  于 2023-06-24  发布在  Shell
关注(0)|答案(1)|浏览(143)

我有一个包含28,000列的csv文件,我想使用unix shell脚本根据另一个csv文件中的标题选择某些列。我不能使用像csvkit这样的工具,因为我在服务器上工作,没有管理员权限安装新工具。我已经读了很多关于这个的帖子,但不能得到我想要的工作,可能是因为以前的答案使用制表符分隔或空格分隔的文本,而不是csv。我是shell脚本的新手(并且不需要经常使用它,因为我通常使用R或Python)。
头文件看起来像这样:

$ cat headers.csv
eid
ABCD001
ABCD005
ABCD021
ABCD022

...等(我需要大约50列,不按顺序)
数据文件是一个csv文件,包含各种格式(数字、字符)的数据,有28,000列,包括我需要的所有50列,头文件中有一个头列。
我试过这篇文章:https://www.unix.com/shell-programming-and-scripting/269610-find-columns-file-based-header-print-new-file.html和这篇文章中的代码:

$ awk 'NR==FNR{a[$0]=NR;next}{for (i in a) printf "%s ", $a[i];print ""}' headers.csv data_file.csv > selected_data_file.csv

但它不工作,可能是因为它正在寻找制表符分隔的文本或空格分隔,我有一个csv文件。它会产生一个巨大的输出文件,所以它没有完成这项工作。
我也读过这篇文章:Create CSV from specific columns in another CSV using shell scripting但是我不能使用列索引,我需要使用另一个文件的头,因为输入数据文件中有很多列。
对于如何修改这段代码以生成包含data_file的所有行的文件,但只包含我需要的50列,我将非常感激。请注意,我不能使用csvkit
输出应该是这样的:

$ cat selected_data_file.csv
eid,ABCD001,ABCD005,ABCD021,ABCD022
AB1, 1, 1, 0.5556, XXXX
AB2, 2, 2, 0.7687, YYYY
AB3, 1, 0, 0.5362, ZZZ

对应于我在headers.csv文件中选择了其标题的列的所有行。
我希望这是有意义的,所有的帮助赞赏!

uqxowvwt

uqxowvwt1#

你很接近了。在读取头文件之后,您需要做的是扫描数据文件的第一行,并选择与头文件匹配的列号。此外,空白不是一种宝贵的资源,使用更多是可以的。

awk '
    NR == FNR {wanted[$0] = 1; next}
    FNR == 1 {
        ncol = 0
        for (i = 1; i <= NR; i++)
            if ($i in wanted)
                columns[++ncol] = i
    }
    {
        for (i = 1; i <= ncol; i++)
            printf "%s%s", $columns[i], OFS
        print ""
    }
' headers.csv data_file.csv > selected_data_file.csv

相关问题