【问题标题】:Shell - diff between files and parameters in each lineShell - 每行中的文件和参数之间的差异
【发布时间】:2016-01-28 17:02:09
【问题描述】:

我正在寻找高级两个文件比较 shell/bash/php。假设我有这样的文件:

文件1

.run file=test_script.sql rev=1.1
.run file=test_sql.sql rev=1.1
.run file=test_drop.sql rev=1.2

文件2

.run file=test_drop.sql rev=1.2
.run file=test_grant.sql rev=1.1
.run file=test_script.sql rev=1.2

获取这些文件之间的差异(忽略行顺序)

.run file=test_grant.sql rev=1.1 #(because new line wasn't in file1 at all)
.run file=test_script.sql rev=1.2 #(because rev changed from rev=1.1 to rev=1.2)

但这还不是全部,我想检查旧文件中是否存在相同的(.run 文件=名称),如果是,则获取它的(rev=编号)。这样最终的输出将如下所示:

文件3:

 test_grant.sql 1.1 1.1
 test_script.sql 1.1 1.2

到目前为止: fgrep -x -v -f file1 file2

得到

.run file=test_grant.sql rev=1.1
.run file=test_script.sql rev=1.2

【问题讨论】:

  • 不多:fgrep -x -v -f file1 file2 得到.run file=test_grant.sql rev=1.1 .run file=test_script.sql rev=1.2
  • file 参数在每个文件中是否唯一?
  • 是的,它们是唯一的,在同一个文件中不能是 file= 同名
  • 你为什么忽略test_sql被删除的事实?
  • 此时我不需要有关已删除内容的信息,只需要新添加或更改。这将使最终输出更加复杂,因为我将在收集的信息上做进一步的工作。除非它将保存在单独的文件中,否则仅将添加和更改的内容告诉一个文件,例如:file_added_modified:.run file=test_grant.sql rev=1.1 .run file=test_script.sql rev=1.2 ,以及删除的文件,例如:file_removed:.run file=test_sql.sql rev=1.1

标签: php bash shell diff comm


【解决方案1】:

这个awk 脚本应该做你想做的事:

awk 'NR==FNR {
    map[$2]=$3
    next;
}

!map[$2] || (map[$2] != $3) {
    sub3=substr($3, index($3,"=")+1)
    subm2=substr(map[$2], index(map[$2],"=")+1)
    print substr($2, index($2,"=")+1), subm2?subm2:sub3, sub3
}' file1 file2

在查看第一个文件 (NR==FNR) 时,将 rev 字段存储在 map 数组中的 file 键下。

在查看第二个文件(第二个块)时,如果此行中的 file 字段不在 map 数组中,或者当前 rev 字段与匹配的 rev 字段不匹配,则打印当前行。

要处理被删除的行,您需要在第二个块之后添加{delete map[$2]},然后在末尾添加END {for (rev in map) {print "Missing: .run "map[rev]" "rev}}

【讨论】:

  • 很好,虽然差异报告会暗示类似print $2, map[$2], map[$3] 的内容,除了在每个值中最多删除=。旁注:成语FR==FNR 真的很容易发生意外,因为如果第一个文件碰巧是空的,它会识别第二个文件。 ARGIND==1 也不起作用,因为 ARGIND 计算像 V=1 这样的非文件参数。就个人而言,我更喜欢ENDFILE{++files},它可以让您使用files 作为一个相当稳健的指标。
  • 也许我读错了。这是 OP 说“所以最终输出将如下所示:...”的地方
  • @rici 是的,我几乎提到NR==FNR 有空文件问题,但不想深入讨论如何没有非 GNU awk 方法这样做是可靠的。我还没有更新到考虑ENDFILE,因为我的大部分awking 都在没有它的CentOS 5(awk 3.1.5)上,但是是的,这是一个很好的成语。我没有注意到 ARGIND 这很烦人。
  • @rici 哦,哇,我完全跳过了那个块。正在更新,谢谢。
  • 完美,谢谢!还意识到我需要做些小改动——如果file= 没有在file2 中列出,那么我不需要对其进行两次修订,而是需要硬编码的第一个条目1.1,所以只需将其添加到那里:awk 'NR==FNR {map[$2]=$3; next;} !map[$2] || (map[$2] != $3) { sub3=substr($3, index($3,"=")+1); subm2=substr(map[$2], index(map[$2],"=")+1); print substr($2, index($2,"=")+1), subm2?subm2:'1.1',sub3}' file1 file2
猜你喜欢
  • 2021-08-26
  • 2011-08-19
  • 2014-10-30
  • 1970-01-01
  • 1970-01-01
  • 2013-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多