泛化一个连接csv文件并添加列的awk程序

pes8fvy9  于 2023-06-27  发布在  其他
关注(0)|答案(4)|浏览(135)

我有两个csv文件:

$ cat numbers.csv
h1,h2
1, 2
3, 4

$ cat letters.csv
h1,h2
a, b
c, d

我想连接两个csv文件,如果行来自letters.csvnumbers.csv,我想添加一个值为letterscolumns的新列,所以我写了这个awk命令(因为我正在尝试awk)来完成这项工作:

$ awk 'NR==1 {print new_column","$0} fname != FILENAME { fname = FILENAME; idx++ } FNR > 1 && idx == 1 { print group1","$0 } FNR > 1 && idx == 2 { print group2","$0 }' new_column=type group1=letters group2=numbers letters.csv numbers.csv

new_column属于要添加的列
group1new_column的值(如果行是从letters.csv文件添加的)
group2new_column的值(如果该行是从numbers.csv文件添加的)
我得到的输出是:

type,h1,h2
letters,a, b
letters,c, d
numbers,1, 2
numbers,3, 4

问题是,我不知道是否有一种方法可以让awk程序运行n个参数和n个文件,而不必每次都像这样重写它:

$ awk '....' new_column=group_name group1=letters group2=numbers ... groupN=whatever  letters.csv numbers.csv .... morefiles_to_N.csv
1mrurvl1

1mrurvl11#

我建议使用单个变量来填充所有需要的名称,然后使用split function将其反序列化,考虑一个简单的例子,假设我有以下内容的file1.txt

1
2
3

file10.txt包含以下内容

10
20

file100.txt,内容如下

100

并且想要融合它们,为来自各自文件的数据命名ABLE、BAKER、CHARLIE,那么我可以这样做

awk -v names=ABLE:BAKER:CHARLIE 'BEGIN{split(names,arr,/:/)}FNR==1{i+=1}{print arr[i] "," $0}' file1.txt file10.txt file100.txt

给出输出

ABLE,1
ABLE,2
ABLE,3
BAKER,10
BAKER,20
CHARLIE,100

说明:我选择了:来分隔名称,在选择时请记住分隔符不能出现在任何名称中。在BEGIN中,我将:处的名称拆分为数组arr,因此arr[1]变为ABLEarr2变为BAKERarr3变为CHARLIE。对于文件(FNR)的每个第一行,我将i增加1。对于每行I print名称,使用,字符与整行($0)连接。

  • (在GNU Awk 5.1.0中测试)*
3wabscal

3wabscal2#

也许像这样

% awk 'NR==1{print "type,"$0} 
       FNR==1{nm=FILENAME; sub(/\..*/,"",nm); next} 
             {print nm","$0}' num.csv let.csv
type,h1,h2
num,1, 2
num,3, 4
let,a, b
let,c, d
lh80um4z

lh80um4z3#

我添加了一个no awk的答案,因为我知道你正在寻找一个使用其他工具(如qsv)的解决方案。
我使用的工具是Miller。跑步

mlr --csv put '$type=sub(FILENAME,"\..+","")' letters.csv numbers.csv

你得到

h1,h2,type
a, b,letters
c, d,letters
1, 2,numbers
3, 4,numbers

put是构建米勒表达式的动词。在这里,我创建了一个新的字段type,我把它等于FILENAME内置变量。我使用sub函数删除文件扩展名。
如果您希望type作为第一个字段,只需添加reorder -f type即可

mlr --csv put '$type=sub(FILENAME,"\..+","")' then reorder -f type letters.csv numbers.csv
oknwwptz

oknwwptz4#

awk -v header=type -v groups=letters,numbers '
    BEGIN{ OFS=","; split(groups, grps,",") } 
    FNR==1{i++} 
    NR==1{ print header,$0; next } 
    FNR!=1{ print grps[i],$0 }
' letters.csv numbers.csv

type,h1,h2
letters,a, b
letters,c, d
numbers,1, 2
numbers,3, 4

相关问题