如何按名称打印某些列?

Bre*_*mas 42 awk

我有以下文件:

id  name  age
1   ed    50
2   joe   70   
Run Code Online (Sandbox Code Playgroud)

我只想打印idage列。现在我只使用awk

cat file.tsv | awk '{ print $1, $3 }'
Run Code Online (Sandbox Code Playgroud)

但是,这需要知道列号。有没有办法做到这一点,我可以使用列名(在第一行指定)而不是列号?

Mat*_*Mat 43

也许是这样的:

$ cat t.awk
NR==1 {
    for (i=1; i<=NF; i++) {
        ix[$i] = i
    }
}
NR>1 {
    print $ix[c1], $ix[c2]
}
$ awk -f t.awk c1=id c2=name input 
1 ed
2 joe
$ awk -f t.awk c1=age c2=name input 
50 ed
70 joe
Run Code Online (Sandbox Code Playgroud)

如果要指定要在命令行上打印的列,可以执行以下操作:

$ cat t.awk 
BEGIN {
    split(cols,out,",")
}
NR==1 {
    for (i=1; i<=NF; i++)
        ix[$i] = i
}
NR>1 {
    for(i=1; i <= length(out); i++)
        printf "%s%s", $ix[out[i]], OFS
    print ""
}
$ awk -f t.awk -v cols=name,age,id,name,id input 
ed 1 ed 50 1 
joe 2 joe 70 2 
Run Code Online (Sandbox Code Playgroud)

(注意-v获取BEGIN块中定义的变量的开关。)

  • 第二个示例没有按预期顺序输出列,`for (i in out)` 没有固有的顺序。`gawk` 提供了 `PROCINFO["sorted_in"]` 作为解决方案,使用 `for( ; ; )` 迭代索引可能更好。 (3认同)

Hot*_*hke 9

csvkit

将输入数据转换为 csv 格式并使用 csv 工具,例如csvcut来自csvkit

$ cat test-cols.dat 
id  name  age
1   ed    50
2   joe   70 
Run Code Online (Sandbox Code Playgroud)

安装 csvkit:

$ pip install csvkit
Run Code Online (Sandbox Code Playgroud)

使用tr其挤压选项-s将其转换为有效的 csv 文件并应用csvcut

$ cat test-cols.dat | tr -s ' ' ',' | csvcut -c id,age
id,age
1,50
2,70
Run Code Online (Sandbox Code Playgroud)

如果要返回旧的数据格式,可以使用 tr ',' ' ' | column -t

$ cat test-cols.dat | tr -s ' ' ',' | csvcut -c id,age | tr ',' ' ' | column -t
id  age
1   50
2   70
Run Code Online (Sandbox Code Playgroud)

笔记


Pet*_*lam 5

只需将 Perl 解决方案放入其中:

#!/usr/bin/perl -wnla

BEGIN {
    @f = ('id', 'age');   # field names to print
    print "@f";           # print field names
}

if ($. == 1) {            # if line number 1
    @n = @F;              #   get all field names
} else {                  # or else
    @v{@n} = @F;          #   map field names to values
    print "@v{@f}";       #   print values based on names
}
Run Code Online (Sandbox Code Playgroud)