【问题标题】:Check if list of patterns from file1.csv is present in file2.csv and change records in file2.csv检查 file2.csv 中是否存在来自 file1.csv 的模式列表并更改 file2.csv 中的记录
【发布时间】:2019-06-11 12:32:34
【问题描述】:

我有 2 个文件 file1.csv 和 file2.csv

file1.csv 仅包含 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 或其他常用实用程序来实现。

编辑: 用清晰的例子更新问题

【问题讨论】:

    标签: bash csv unix awk sed


    【解决方案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 更改为不同的文件检查方法,例如ARGIND==1 用于GNU awk,或FILENAME=="file1.csv" 等。

    如果需要处理大量数据,将a[$1]++ 更改为a[$1]=1 会略微提高速度。
    此外,如果您想保留标题(或第 2 行),那么最好在 FNR>1FNR>2 时开始更改数组 a。自己改进命令,我相信你明白了;)

    NR==FNR 表示第一个文件,因为NR 表示 N现在的总 Record 数,FNR 表示当前 File 的 Nnumber of Records。
    a 是一个数组,实际上将 $1 保存为键。
    next 跳过其他块执行。

    NR==FNR为false时,表示它不是第一个文件,第一个块不会被执行。
    (你也可以在块前使用NR>FNR来指定它,但由于我在NR==FNR块中使用了next,所以没有必要。)
    然后其他指令启动,a[$1] 是判断数组a 中是否存在key(通过引用值,字面上检查key exists 实际上应该是$1 in a),如果存在,则更改$ 5。
    最后1是指定一个真值,是{print}的快捷方式。
    (由于没有块的表达式,将隐含{print},并且当前面的表达式计算为true时执行块,1始终为真。)

    【讨论】:

    • 我更新了我的问题,我的 file2.csv 有重复的行。你的解决方案也适用吗?
    • @Abhinay 你不能测试一下吗?
    • 我确实试过了,但是文件真的很大,不知道能不能用。。得到结果后我会更新。只是想让您知道 file2 中的记录是重复的。
    • 谢谢!!它按预期工作。你介意解释一下逻辑吗?
    • @Abhinay 您可以轻松搜索它,或阅读文档。但是,我还是更新了答案来解释它。
    【解决方案2】:

    你可以试试 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,
    
    $
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多