【问题标题】:Shell Script logic NR==FNR getting Failed for Case 2Shell 脚本逻辑 NR==FNR 在案例 2 中失败
【发布时间】:2016-12-02 17:50:52
【问题描述】:

我有两个文件名 1) File-New 2) File-Old。它们包含如下所示的数据,

案例 1

文件-新建

7! J9AA-104445-A-BOM-50! REINF RR KIT FLR S/M LH! 35!
8! J9BB-103365-A-BOM-50! MBR REINF  FLR SD LH! 22!
7! JWZZ-102225-A-MOM-50! RZFIF RR KRT FLR W/Z LH! 15!

旧文件

7! J9AA-104445-A-BOM-50! REINF RR KIT FLR S/M LH! 34!
8! J9BB-103365-A-BOM-50! MBR REINF  FLR SD LH! 21!
7! JWZZ-102225-A-MOM-50! RZFIF RR KRT FLR W/Z LH! 14!

当我们对两个文件运行 awk -F"!" 'NR==FNR{++a[$2,$4];next} !(a[$2,$4])' 逻辑时,预期的输出是,

$ /usr/xpg4/bin/awk -F"!" 'NR==FNR{++a[$2,$4];next} 
                           !(a[$2,$4])' "File-New" "File-Old"

   7! J9AA-104445-A-BOM-50! REINF RR KIT FLR S/M LH! 34!
   8! J9BB-103365-A-BOM-50! MBR REINF  FLR SD LH! 21!
   7! JWZZ-102225-A-MOM-50! RZFIF RR KRT FLR W/Z LH! 14!

从输出中我们可以看到命令-F"!" 'NR==FNR{++a[$2,$4];next} !(a[$2,$4])' 的逻辑是为了打印“File-Old”中的差异而编写的。但是如果两个文件的数据发生如下变化,上述逻辑就会失败,

案例 2

文件-新建

7! J9AA-104445-A-BOM-50! REINF RR KIT FLR S/M LH! 35!
8! J9BB-103365-A-BOM-50! MBR REINF  FLR SD LH! 22!
7! JWZZ-102225-A-MOM-50! RZFIF RR KRT FLR W/Z LH! 15!
7! J9AA-104445-A-BOM-50! REINF RR KIT FLR S/M LH! 34!
8! J9BB-103365-A-BOM-50! MBR REINF  FLR SD LH! 21!

文件-旧

7! J9AA-104445-A-BOM-50! REINF RR KIT FLR S/M LH! 34!
8! J9BB-103365-A-BOM-50! MBR REINF  FLR SD LH! 21!
7! JWZZ-102225-A-MOM-50! RZFIF RR KRT FLR W/Z LH! 14!
7! J9AA-104445-A-BOM-50! REINF RR KIT FLR S/M LH! 34!
8! J9BB-103365-A-BOM-50! MBR REINF  FLR SD LH! 21!

案例 2

运行相同的逻辑
$ /usr/xpg4/bin/awk -F"!" 'NR==FNR{++a[$2,$4];next} 
                           !(a[$2,$4])' "File-New" "File-Old"

   7! JWZZ-102225-A-MOM-50! RZFIF RR KRT FLR W/Z LH! 14!

预期结果是

  7! J9AA-104445-A-BOM-50! REINF RR KIT FLR S/M LH! 34!
  8! J9BB-103365-A-BOM-50! MBR REINF  FLR SD LH! 21!
  7! JWZZ-102225-A-MOM-50! RZFIF RR KRT FLR W/Z LH! 14!

有人能建议我在逻辑上需要改变什么-F“!” 'NR==FNR{++a[$2,$4];next} !(a[$2,$4])' 在不更改文件的情况下获得 case 2 的预期输出订购“新文件”“旧文件”。

注意:我们必须保持传递给命令的文件顺序是 Fix,即“File-New”“File-Old”

【问题讨论】:

  • 请说明您希望达到的目标。是的,我们可以看到你的命令的逻辑,但它输出的正是它应该输出的,所以你的期望很可能是错误的。
  • 你必须明确你想要得到什么。您的代码打印 old 文件中与 new 文件不同的行。但是您的预期输出包括公共行和一个不同的行
  • 我的期望是在比较两个文件之后只打印 $2 相同和 $4 不同的行。也不要在 File-New 中打印新添加的行。一位专家“Valentin B”在逻辑下方建议 /usr/xpg4/bin/awk -F'!' 'NR==FNR{++a[$2,$4,FNR];next} !(a[$2,$4,FNR])' "File-New" "File-Old" 这可以正常工作,但如果 "File-New " 包含 File-Old 中不存在的新条目,则此逻辑失败。任何人都可以改进上述代码以获得上述预期结果。

标签: bash shell unix awk


【解决方案1】:

您正在使用的awk sn-p 构造一个字典,其键等于第二个和第四个字段的值(使用“!”分隔字段)。它未能达到您的预期,因为例如对于这一行(“File-new”中的第 2 行):

8! J9BB-103365-A-BOM-50! MBR REINF  FLR SD LH! 22!

这一行的变化

8! J9BB-103365-A-BOM-50! MBR REINF  FLR SD LH! 21!

“文件旧”中还有另一行具有相同的第 2 和第 4 字段。因此数组a 的键[J9BB-103365-A-BOM-50,21] 处的值不为零,因此不会打印该行。如果您希望监控这两个字段上每一行的更改,您还必须将行号存储在您的数组中,从而产生:

awk -F'!' 'NR==FNR{++a[$2,$4,FNR];next} 
                       !(a[$2,$4,FNR])' "File-New" "File-Old"

也许您还希望通过打印行号来完成此操作:

awk -F'!' 'NR==FNR{++a[$2,$4,FNR];next} 
          !(a[$2,$4,FNR]){printf "Line %d changed: %s\n", FNR, $0}' "File-New" "File-Old"

输出:

Line 1 changed: 7! J9AA-104445-A-BOM-50! REINF RR KIT FLR S/M LH! 34!
Line 2 changed: 8! J9BB-103365-A-BOM-50! MBR REINF  FLR SD LH! 21!
Line 3 changed: 7! JWZZ-102225-A-MOM-50! RZFIF RR KRT FLR W/Z LH! 14!

【讨论】:

  • 我的期望是在比较两个文件之后只打印 $2 相同和 $4 不同的行。也不要在 File-New 中打印新添加的行。如果 File-New 包含 File-Old 中不存在的新条目,您建议的代码的工作方式会有所不同。
  • 文件 新 7! J9AA-50! ! 35! 8! J9BB-50! ! 22! 7!测试3!测试3! 8 7! JWZZ-50! ! 15! 7! J9AA-50! ! 34! 8! J9BB-50! ! 21!文件-旧 7! J9AA-50! ! 34! 8! J9BB-50! ! 21! 7! JWZZ-50! ! 14! 7! J9AA-50! ! 34! 8! J9BB-50! ! 21!对于上述情况,您建议的代码失败,/usr/xpg4/bin/awk -F'!' 'NR==FNR{++a[$2,$4,FNR];next} !(a[$2,$4,FNR])' "File-New" "File-Old" 预期结果:7! J9AA-50! ! 34! 8! J9BB-50! ! 21! 7! JWZZ-50! ! 14!你能建议改变吗
猜你喜欢
  • 2017-04-20
  • 2015-12-05
  • 1970-01-01
  • 2014-01-14
  • 2022-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-26
相关资源
最近更新 更多