linux awk比较两个csv文件并创建一个带有标志的新文件

标签 linux bash csv awk export-to-csv

我有 2 个 CSV 文件,我需要将它们与新格式化的文件进行比较并找出差异。示例如下。

旧文件

DTL,11111111,1111111111111111,11111111111,Y,N,xx,xx
DTL,22222222,2222222222222222,22222222222,Y,Y,cc,cc
DTL,33333333,3333333333333333,33333333333,Y,Y,dd,dd
DTL,44444444,4444444444444444,44444444444,Y,Y,ss,ss
DTL,55555555,5555555555555555,55555555555,Y,Y,qq,qq

新文件

DTL,11111111,1111111111111111,11111111111,Y,Y,xx,xx
DTL,22222222,2222222222222222,22222222222,Y,N,cc,cc
DTL,44444444,4444444444444444,44444444444,Y,Y,ss,ss
DTL,55555555,5555555555555555,55555555555,Y,Y,qq,qq
DTL,77777777,7777777777777777,77777777777,N,N,ee,ee

输出文件

我想比较新旧 CSV 文件并找出影响新文件的更改并更新一个标志以表示这些更改

U - 如果新文件记录已更新 D - 如果旧文件中存在的记录在新文件中被删除 N - 如果新文件中存在的记录在旧文件中不可用

示例输出文件是这样的。

DTL,11111111,1111111111111111,11111111111,Y,Y,xx,xx U
DTL,22222222,2222222222222222,22222222222,Y,N,cc,cc U
DTL,33333333,3333333333333333,33333333333,Y,Y,dd,dd D
DTL,77777777,7777777777777777,77777777777,N,N,ee,ee N

我使用了 diff 命令,但它也会重复更新的记录,这不是我想要的。

 DTL,11111111,1111111111111111,11111111111,Y,N,xx,xx
 DTL,22222222,2222222222222222,22222222222,Y,Y,cc,cc
 DTL,33333333,3333333333333333,33333333333,Y,Y,dd,dd
  ---
 DTL,11111111,1111111111111111,11111111111,Y,Y,xx,xx
 DTL,22222222,2222222222222222,22222222222,Y,N,cc,cc
 5a5
 DTL,77777777,7777777777777777,77777777777,N,N,ee,ee

我也使用 AWK 单行命令来过滤我的记录

 awk 'NR==FNR{A[$1];next}!($1 in A)' FS=: old.csv new.csv

问题是我没有得到只属于旧文件的记录。 这是

DTL,33333333,3333333333333333,33333333333,Y,Y,dd,dd

我也启动了一个驱动的 bash 脚本来实现这一点,但没有找到一个很好的例子的帮助。

 myscript.awk

BEGIN { 
        FS = ","    # input field seperator 
        OFS = ","   # output field seperator
}

NR > 1 {
    #flag 
    # N - new record  D- Deleted U - Updated

id = $1
    name = $2
    flag = 'N'

   # This prints the columns in the new order. The commas tell Awk to use the     character set in OFS
    print id,name,flag
}

 >> awk -f  myscript.awk  old.csv new.csv > formatted.csv

最佳答案

这可能对你有用:

diff  -W999 --side-by-side OLD NEW |
sed '/^[^\t]*\t\s*|\t\(.*\)/{s//\1 U/;b};/^\([^\t]*\)\t*\s*<$/{s//\1 D/;b};/^.*>\t\(.*\)/{s//\1 N/;b};d'
DTL,11111111,1111111111111111,11111111111,Y,Y,xx,xx U
DTL,22222222,2222222222222222,22222222222,Y,N,cc,cc U
DTL,33333333,3333333333333333,33333333333,Y,Y,dd,dd D
DTL,77777777,7777777777777777,77777777777,N,N,ee,ee N

遵循相同思路的 awk 解决方案:

diff -W999 --side-by-side OLD NEW |
awk '/[|][\t]/{split($0,a,"[|][\t]");print a[2]" U"};/[\t] *<$/{split($0,a,"[\t]* *<$");print a[1]" D"};/>[\t]/{split($0,a,">[\t]");print a[2]" N"}'
DTL,11111111,1111111111111111,11111111111,Y,Y,xx,xx U
DTL,22222222,2222222222222222,22222222222,Y,N,cc,cc U
DTL,33333333,3333333333333333,33333333333,Y,Y,dd,dd D
DTL,77777777,7777777777777777,77777777777,N,N,ee,ee N

关于linux awk比较两个csv文件并创建一个带有标志的新文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9528202/

相关文章:

ruby - 如何在 Ruby 中加载包含两列的 CSV 并将其保存在 2 个数组中

c - 估计代码在本地linux系统上的执行时间

python - 如何在 Linux Debian 上更新 Python PygreSQL 包?

linux - 根文件夹下的大文件

Bash:删除具有唯一时间戳的重复行

python - 读取制表符分隔的文件,第一列作为键,其余列作为值

linux - 如何为 linux/unix 命令分配 RAM 和堆空间?

bash - Bash脚本大于运算符给出语法错误

bash - 为命令格式化 bash 变量

来自 CSV IndexError 的 Python 字典