我有以下文件:
id name age
1 ed 50
2 joe 70
我只想打印id
和age
列。现在我只使用awk
:
cat file.tsv | awk '{ print $1, $3 }'
然而,这需要知道列号。有没有办法可以使用列名(在第一行指定)而不是列号?
答案1
也许是这样的:
$ 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
如果你想指定在命令行上打印的列,你可以这样做:
$ 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
(注意-v
用于获取块中定义的变量的开关BEGIN
。)
答案2
csvkit
将输入数据转换为 csv 格式并使用 csv 工具,例如csvcut
来自csvkit
:
$ cat test-cols.dat
id name age
1 ed 50
2 joe 70
安装 csvkit:
$ pip install csvkit
tr
与其挤压选项一起使用-s
,将其转换为有效的 csv 文件并应用csvcut
:
$ cat test-cols.dat | tr -s ' ' ',' | csvcut -c id,age
id,age
1,50
2,70
如果你想恢复到旧的数据格式,你可以使用tr ',' ' ' | column -t
$ cat test-cols.dat | tr -s ' ' ',' | csvcut -c id,age | tr ',' ' ' | column -t
id age
1 50
2 70
笔记
csvkit 还支持不同的分隔符(共享选项
-d
或--delimiter
),但返回 csv 文件:如果文件仅使用空格来分隔列(根本没有制表符),则以下工作
$ csvcut -d ' ' -S -c 'id,age' test-cols.dat id,age 1,50 2,70
如果文件使用制表符分隔列,则以下工作和
csvformat
可用于取回 tsv 文件:$ csvcut -t -c 'id,age' test-cols.dat | csvformat -T id age 1 50 2 70
据我检查,只允许使用一个选项卡。
csvlook
可以将表格格式化为 Markdown 表格格式$ csvcut -t -c "id,age" test-cols.dat | csvlook | id | age | | -- | --- | | 1 | 50 | | 2 | 70 |
UUOC(无用的猫):我喜欢用这种方式构建命令。
答案3
只是将 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
}
答案4
物有所值。这可以处理源中任意数量的列,以及要打印的任意数量的列,无论您选择什么输出顺序;只需重新排列参数...
例如。称呼:script-name id age
outseq=($@)
colnum=($(
for ((i; i<${#outseq[@]}; i++)) ;do
head -n 1 file |
sed -r 's/ +/\n/g' |
sed -nr "/^${outseq[$i]}$/="
done ))
tr ' ' '\t' <<<"${outseq[@]}"
sed -nr '1!{s/ +/\t/gp}' file |
cut -f $(tr ' ' ','<<<"${colnum[@]}")
输出
id age
1 50
2 70