csvkit

csvkit

假设我有以下制表符分隔的文件data.tsv

1 a 3
2 b 2
3 a 10
2 c 2
2 a 8

现在,我想交换第 1 列中的值 - 比如说,将它们从 ID 转换为名称 - 通过使用以下命令map.tsv

1 foo
2 bar
3 baz

结果应该是:

foo a 3
bar b 2
baz a 10
bar c 2
bar a 8

我知道对于可以使用一些 AWK 技巧进行映射,但我希望能够对多个列使用多个映射,并进行如下简单的调用:

$ my_map_command 1:map.tsv < data.tsv

有没有一个命令可以做类似的事情?

答案1

csvkit

csvjoin包中的命令csvkit可用于实现类似的行为:

$ csvjoin -tH -c 1,1 data.tsv map.tsv 2> /dev/null
a,b,c,b2
1,a,3,foo
2,b,2,bar
3,a,10,baz
2,c,2,bar
2,a,8,bar

csvcut重新排序/删除列很简单,可以从同一个包中完成。

核心工具

也可以使用该标准join(1),但它需要对数据进行排序(如果未排序,还需要对地图进行排序):

$ join -j1 -t '       ' <(sort -k1 data.tsv) map.tsv
1       a       3       foo
2       a       8       bar
2       b       2       bar
2       c       2       bar
3       a       10      baz

这两种情况一次只能执行一个映射,因此多个映射需要通过管道传输到进一步的调用。

答案2

将其放入名为的文件中my_map_command

#!/usr/bin/awk -f
FNR==NR{map[$1]=$2}
FNR!=NR{
    printf "%s%s",map[$1],OFS
    for (i=2; i<=NF; i++) printf "%s%s",$i,OFS
    printf "\n"
}

然后运行:

chmod u+x my_map_command

像这样调用你的脚本:

./my_map_command map.tsv data.tsv

多个地图文件:

./my_map_command <(cat map1.tsv map2.tsv) data.tsv

答案3

在文件参数之间分配一个变量:

awk '!data{map[$1]=$2; next} $1 in map{$1=map[$1]} 1' map1 map2... data=1 data
  • 将值读入map数组,直到给出标志为止
  • 给出标志值(data=1参数)后,将数据中的字段交换为映射值

awk '
!data {
    map[field,$1]=$2
    maps[field]
    next
}
{
    for (i in maps)
        if ((i,$i) in map)
            $i=map[i,$i]
}
1' field=1 map1 field=2 map2 data=1 data
  • 字段 1 indata映射到值 frommap1
  • 字段 2 indata映射到值 frommap2

答案4

或者只是使用您可能已经知道的语言来查询表格数据:;

语法很简单:q "<SQL Query>",或者q -t "…"如果您的文件是 tsv,或者-d …其他分隔符。您的查询将是:

SELECT m.c2, d.c2, d.c3 
FROM data.tsv AS d INNER JOIN map.tsv AS m
                   ON d.c1==m.c1

q - text as data包装好的 到处)是一个巧妙的工具,可以应用SQL任何表格、分隔数据。即使 STDIN 也可以工作,只需指定“-”作为文件名,考虑JOIN - as m用您输入的内容替换 map.tsv 。

不错的“奖励” q:您可以使用 SQL ORDERGROUP以及进行计算!展示这一切:

q 'SELECT m.c2 AS I, d.c2, d.c3, ROUND(d.c3*0.4, 2) as b
   FROM data.tsv AS d INNER JOIN - AS m
                      ON d.c1==m.c1
   ORDER BY I' < map.tsv

bar b 2 0.8
bar c 2 0.8

注意:名称“q”完全无法被谷歌搜索,因此在搜索时添加“text-as-data”或“harelba”(作者)。

相关内容