我有以下文件:
id name age
1 ed 50
2 joe 70
Run Code Online (Sandbox Code Playgroud)
我只想打印id
和age
列。现在我只使用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
块中定义的变量的开关。)
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)
笔记
csvkit 还支持不同的分隔符(共享选项 -d
或--delimiter
),但返回一个 csv 文件:
如果文件仅使用空格来分隔列(根本没有制表符),则以下工作
$ csvcut -d ' ' -S -c 'id,age' test-cols.dat
id,age
1,50
2,70
Run Code Online (Sandbox Code Playgroud)如果文件使用制表符来分隔列,则以下工作csvformat
可用于取回 tsv 文件:
$ csvcut -t -c 'id,age' test-cols.dat | csvformat -T
id age
1 50
2 70
Run Code Online (Sandbox Code Playgroud)
据我检查,只允许一个标签。
csvlook
可以将表格格式化为降价表格格式
$ csvcut -t -c "id,age" test-cols.dat | csvlook
| id | age |
| -- | --- |
| 1 | 50 |
| 2 | 70 |
Run Code Online (Sandbox Code Playgroud)UUOC(Useless Use Of Cat):我喜欢这种构造命令的方式。
只需将 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)