根据相应第一行的内容查找列

根据相应第一行的内容查找列

所以我有一个TSV看起来像这样的文件:

Hello world how are you
1 2 3 4 5
6 7 8 9 0

(在上面的手写玩具示例中,我用一个空格分隔了每一行中的所有内容。)

我的目标是获取包含“how”和“are”的列作为第一行值。因此,输出将如下所示:

how are
3 4
8 9

问题是我不知道这些模式(即“如何”和“是”)将出现在哪一列。因此,例如,该TSV文件实际上可以这样排列:

Hello how world are you
1 3 2 4 5
6 8 7 9 0

我知道如何处理这个问题,例如python(只需转置文件,然后选择我想要的行),但我想在 shell 中执行此操作(出于原因)。问题是,我不知道该怎么做。我知道使用命令行实用程序也可以进行转置(例如,参见这里)但如果​​可以的话,我想避免使用那些庞大的代码。我最初的、头脑简单的解决方案只是grep“如何”和“是”,但这显然返回了整个文件,这就是我一直陷入困境的地方。

任何帮助或指示将不胜感激!

编辑:我必须提到,我没有在这台机器上安装任何新工具的权限。我也很不确定它实际上带有什么。如果有帮助的话,这是Scientific Linux 7.3 (Nitrogen)

答案1

使用csvtool1:

csvtool -t ' ' -u ' ' namedcol how,are file

-t Input separator char.
-u Output separator char.

 namedcol <names>
    Assuming the first row of the CSV file is a list of column headings,
    this returned the column(s) with the named headings.

^sudo apt install csvtool

答案2

通过awk您可以检查第一行是否有匹配的关键字,记下列号,然后打印相应的值:

#first line -> Select columns based on keyword
NR==1 {
  for (i = 1; i <= NF; i++) {
    if ( $i == "how" ) {col_how=i}
    if ( $i == "are" ) {col_are=i}
  }
}
#print selected columns including header line
NR>=1 {
  print $col_how, $col_are
}

另存为egscript.awk并执行

awk -f script.awk datafile

编辑:

您的转置和 ing 想法也grep可以轻松实现:

datamash transpose <datafile | grep 'how\|are' | datamash transpose

用于-t ' '将空格定义为分隔符。然而,对于很长的文件,这可能会遇到 RAM 限制。但是,大多数机器上可能未按标准安装。

答案3

$ cat tst.awk
BEGIN {
    cols = (cols == "" ? "how are" : cols)
    nf = split(cols,tgts)
    FS = OFS = "\t"
}
NR==1 {
    for (i=1; i<=NF; i++) {
        f[$i] = i
    }
}
{
    for (i=1; i<=nf; i++) {
        printf "%s%s", $(f[tgts[i]]), (i<nf ? OFS : ORS)
    }
}

$ awk -f tst.awk file
how     are
3       4
8       9

$ awk -v cols='are world you Hello' -f tst.awk file
are     world   you     Hello
4       2       5       1
9       7       0       6

相关内容