【问题标题】:Finding differences between 2 csv files using unix command or shell scripting使用 unix 命令或 shell 脚本查找 2 个 csv 文件之间的差异
【发布时间】:2018-06-15 09:43:41
【问题描述】:

我是 Unix 和 shell 脚本的新手。我正在尝试使用 Unix 命令查找 2 个 .csv 文件之间的差异。有一些条件,我必须根据这些条件找到差异。

  1. 更新到一个条目,即 file1 中的任何行(唯一 id 是员工 id)都存在于 file2 中,但另一列的值不同。它被视为更新。在这种情况下,我需要来自 file2 的条目
  2. 如果文件2中存在条目而文件中不存在,则认为添加了新员工。我需要 file2 中的那一行。
  3. 如果文件1中存在条目,文件2中不存在,则认为删除了员工。我需要 file1 中的那一行。

我可以使用comm -23 sorted_file_2.csv sorted_file_1.csv > updates.csv 找到更新和新记录,但找不到已删除的条目。

我已经使用以下命令检查了解决方案

grep -v -x -f sorted_file_2.csv sorted_file_1.csv > deleted.csv

awk 'NR==FNR{a[$0]=1;next}!a[$0]' sorted_file_2.csv sorted_file_1.csv > deleted.csv

diff sorted_file_1.csv sorted_file_2.csv > deleted.csv

上面的命令总是给我更新和删除的条目。我正在寻找 file1 中不在 file2 中的唯一条目

附:这两个文件可以包含上述所有 3 种情况。我需要在两个 csv 文件中输出。一个用于更新/新记录,另一个用于已删除记录。

文件1.csv

行|Employee_ID|薪水|职称 1|John|2000|文员 2|Smith|3000|主管 3|Jenny|1000|实习生 4|Vicky|5000|经理

文件2.csv

行|Employee_ID|薪水|职称 1|John|2000|文员 2|Smith|4000|高级主管 4|Vicky|5000|经理 5|詹姆斯|5000|审计员

在以上2个文件中 file2 中的第 2 行是更新,第 5 行是新条目。它们都可以合并到单个文件中作为

Update_new.csv

2|史密斯|4000|高级主管
5|詹姆斯|5000|审计员

删除的条目是 file1.csv 中的第 3 行,而 file2.csv 中不存在该条目,要保存在单独的文件中 删除的.csv

3|珍妮|1000|实习生

即使我能够将所有两个文件添加到单个文件中,并使用一个额外的列指定 "UPDATED","NEW","DELETED" 值也可以。

【问题讨论】:

  • 为什么不使用diff
  • 我只需要 csv 格式的结果,以便我可以被 java 应用程序进一步读取。需要进一步更新、添加和删除来自其他应用程序的条目
  • 发布具有预期输出的两个文件的样本。

标签: shell unix


【解决方案1】:

您可以使用 diff 本身轻松做到这一点。

我使用的测试文件

1.csv:

a,1
b,2
d,3
f,5

2.csv:

b,2
c,6
d,3
f,4

这是diff的输出

$ diff 1.csv 2.csv
1d0
< a,1
2a2
> c,6
4c4
< f,5
---
> f,4

您可以搜索字母'a'、'd'、'c'来添加、删除和更改行。这是一个如何获取添加行的示例

$ diff 1.csv 2.csv | grep -A1 '^[0-9]*a'
2a2
> c,6

您可以使用另一个 sed 命令正确地仅提取 csv

$ diff 1.csv 2.csv | grep -A1 '^[0-9]*a' | sed -n '/^[><]/s/[><] \(.*\)$/\1/p'
c,6

您可以轻松地将 grep 和 sed 命令更改为您想要的任何格式。

【讨论】:

  • 你的答案只是解决了问题的一部分。它只给我新添加的条目。即使对于存在于 file1 但不在 file2 中的条目,Diff 命令也会显示“c”。
  • 您必须相应地修改最后一个命令以获取“删除”和“更改”文件。 Diff 有时会将多个更改的行组合在一起。我想不出办法来避免这种情况。也许首先使用唯一键对文件进行排序,然后使用差异? 编辑:您绝对应该先排序,以保持一致的顺序。如果您更改整体的顺序,diff 也会标记它
【解决方案2】:

使用 awk:

$ awk -F\| '
NR==FNR {                       # store first file to a hash
    a[$1]=$0                    # $1 is the key
    next
}
($1 in a) {                     # process second file. If key in a
    if(a[$1]!=$0)               # but data has changed
        print > "updated"       # output to updated file
    delete a[$1]                # delete entry from hash
    next                        # skip to next record in file
}
{
    print > "updated"           # if $1 not in a, it is new, output
}
END {                           # after file 2
    for(i in a)                 # print all leftovers from file 1
        print a[i] > "deleted"  # output to deleted
}' 1.csv 2.csv

结果:

$ cat deleted
3|Jenny|1000|Intern
$ cat updated
2|Smith|4000|Senior Supervisor
5|James|5000|Auditor

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多