我有2个文件file1.csv和file2.csv
file1.csv仅包含100列的1列。
aaa
ddd
fff
ggg
file2.csv包含5个具有数千行的字段。
aaa,2,3,4,
aaa,2,3,4,
bbb,2,3,4,
ccc,2,3,4,
ccc,2,3,4,
ddd,2,3,4,
ddd,2,3,4,
ddd,2,3,4,
eee,2,3,4,
fff,2,3,4,
ggg,2,3,4,
hhh,2,3,4,
hhh,2,3,4,
我的任务是检查file1.csv中存在的col1是否与fil2.csv中的col1相匹配,然后将file2.csv中的第5列更改为Y
所需的输出
aaa,2,3,4,Y
aaa,2,3,4,Y
bbb,2,3,4,
ccc,2,3,4,
ccc,2,3,4,
ddd,2,3,4,Y
ddd,2,3,4,Y
ddd,2,3,4,Y
eee,2,3,4,
fff,2,3,4,Y
ggg,2,3,4,Y
hhh,2,3,4,
hhh,2,3,4,
我尝试过的是
for i in $(cat file1.csv); do awk -F "," '$1==$i{$5="Y"}1' OFS="," file2.csv ; done
但是我只得到匹配的记录,而没有得到不匹配的记录。
有没有更好的方法可以在UNIX中使用awk,sed或其他常用实用程序来实现这一目标。
编辑: 用明确的示例更新问题
答案 0 :(得分:1)
不需要那样做,只需awk读取两个文件就可以了:
awk -F, 'NR==FNR{a[$1]++;next;}a[$1]{$5="Y"}1' file1.csv file2.csv
不确定标题和第二行是否是您的解释方式,是否想摆脱它们:
awk -F, 'NR==FNR{a[$1]++;next;}a[$1]{$5="Y"}FNR>2' file1.csv file2.csv
请注意,如果file1.csv可以为空,则应将NR==FNR
更改为其他文件检查方法,例如GNU awk的ARGIND==1
或FILENAME=="file1.csv"
等。
如果要处理大量数据,请将a[$1]++
更改为a[$1]=1
会稍微提高速度。
另外,如果要保留标题(或第二行),则最好在a
或FNR>1
时开始更改数组FNR>2
。自己完善命令,我相信您已经明白了;)
NR==FNR
表示第一个文件,因为NR
表示现在总共 R 个折线的 N 个数字,而FNR
表示当前的< strong> F ile的 R 折线的数量。
a
是一个实际将$1
保存为键的数组。
next
跳过其他程序块的执行。
如果NR==FNR
为false,则表示它不是第一个文件,因此不会执行第一个块。
(您也可以在块之前使用NR>FNR
来指定它,但是由于我在next
块中使用了NR==FNR
,所以没有必要。)
然后使用其他指令,a[$1]
判断键是否存在于数组a
中(通过引用该值,从字面上检查key exists
实际上应该是$1 in a
),如果存在,则更改$ 5。
最后一个1
是要指定一个真值,它是{print}
的快捷方式。
(由于表达式没有块,因此将隐含{print}
,并且在计算为true
始终为1
的先前表达式时,将执行块。)
答案 1 :(得分:0)
您可以尝试Perl解决方案
$ perl -F, -lane 'BEGIN {%kv=map{chomp;$_=>1} qx(cat file1.csv) } print "$_", $kv{$F[0]}? "Y" : "" ' file2.csv
aaa,2,3,4,Y
aaa,2,3,4,Y
bbb,2,3,4,
ccc,2,3,4,
ccc,2,3,4,
ddd,2,3,4,Y
ddd,2,3,4,Y
ddd,2,3,4,Y
eee,2,3,4,
fff,2,3,4,Y
ggg,2,3,4,Y
hhh,2,3,4,
hhh,2,3,4,
$ cat file1.csv
aaa
ddd
fff
ggg
$ cat file2.csv
aaa,2,3,4,
aaa,2,3,4,
bbb,2,3,4,
ccc,2,3,4,
ccc,2,3,4,
ddd,2,3,4,
ddd,2,3,4,
ddd,2,3,4,
eee,2,3,4,
fff,2,3,4,
ggg,2,3,4,
hhh,2,3,4,
hhh,2,3,4,
$