在文件中的特定列上使用 Diff

kic*_*s13 10 scripting ksh diff shell-script file-comparison

是否可以在文件中的特定列上使用差异?

文件 1

Something  123 item1
Something  456 item2
Something  768 item3
Something  353 item4
Run Code Online (Sandbox Code Playgroud)

文件 2

Another   123 stuff1
Another   193 stuff2
Another   783 stuff3
Another   353 stuff4
Run Code Online (Sandbox Code Playgroud)

输出(预期)

Something  456 item2
Something  768 item3
Another   193 stuff2
Another   783 stuff3
Run Code Online (Sandbox Code Playgroud)

我想要diff每个文件的第二列,然后,结果将包含 diff-ed 列,但与整行一起。

Lar*_*ach 16

awk是比较文件列的更好工具。例如,请参阅以下答案:比较不同文件的两列,如果匹配打印——对于匹配列的打印行,也有类似的答案。

由于您想打印匹配的行,我们可以创建一个awk命令来打印 file2 中在 file1 中没有看到第2 列的行:

$ awk 'NR==FNR{c[$2]++;next};c[$2] == 0' file1 file2
Another   193 stuff2
Another   783 stuff3
Run Code Online (Sandbox Code Playgroud)

正如 terdon 在上述问题中类似的解释,

  • NR==FNR: NR 是当前输入的行号,FNR 是当前文件的行号。只有在读取第一个文件时,两者才会相等。
  • c[$2]++; next:如果这是第一个文件,则保存c数组中的第二个字段。然后,跳到下一行,以便这仅应用于第一个文件。
  • c[$2] == 0: else 块只有在这是第二个文件时才会执行,所以我们检查是否已经看到了这个文件的字段 2 ( c[$2]==0),如果已经看到,我们打印该行。在 中awk,默认操作是打印该行,因此如果c[$2]==0为 true,则将打印该行。

但是您还需要 file1 中第 2 列在 file2 中不匹配的行。这可以通过简单地在同一命令中交换它们的位置来获得:

$ awk 'NR==FNR{c[$2]++;next};c[$2] == 0' file2 file1
Something  456 item2
Something  768 item3
Run Code Online (Sandbox Code Playgroud)

所以现在您可以通过使用awk两次来生成您想要的输出。也许拥有更多awk专业知识的人可以一次性完成。

您用 标记了您的问题/ksh,因此我假设您使用的是 korn shell。在ksh你可以定义一个函数为你的差异,比方说diffcol2,让你的工作更轻松:

diffcol2()
{
   awk 'NR==FNR{c[$2]++;next};c[$2] == 0' $2 $1      
   awk 'NR==FNR{c[$2]++;next};c[$2] == 0' $1 $2      
}
Run Code Online (Sandbox Code Playgroud)

这具有您想要的行为:

$ diffcol2 file1 file2
Something  456 item2
Something  768 item3
Another   193 stuff2
Another   783 stuff3
Run Code Online (Sandbox Code Playgroud)