比较未排序和混合大小写文件以仅选择唯一条目

比较未排序和混合大小写文件以仅选择唯一条目

在对文件进行两种方式比较时,我遇到了一些挫折。

  • 文件1
    bill 
    telephone
    address_1
    address_2
    address_3
    city
    postal_code
    
  • 文件2
    Bill
    Bill_ID
    Telephone
    Address_1
    Address_2
    city
    Postal_Code
    

我正在尝试填充两个文件中唯一的值。所以我的预期结果应该是这样的:

+-----------+---------+
|   File1   |  File2  |
+-----------+---------+
|           | Bill_ID |
| address_3 |         |
+-----------+---------+

我试图实现它的事情:

  • sdiff首先按字典顺序对其进行排序,但它产生了所有列。

  • 或者

    sdiff -Wais File1.txt File2.txt | awk '{print $1}' | sort -u
    

    但我需要通过反转文件来运行它两次。

  • comm但有这个错误

    comm -23 < (sort File1.txt) <(sort File2.txt)
    bash: syntax error near unexpected token '('
    
  • diff但输出似乎不正确。

    diff File_1 File_2 | grep '^>' | cut -c 3-
    

在所有这些情况下,我面临的问题只是比较。我还无法继续填充正确的表。

答案1

您可以使用join文本的小写版本作为连接键:

$ preprocess() { awk -v OFS='\t' '{print tolower($0), $0}' | sort -t $'\t' -k1,1; }
$ join -t $'\t' -o1.2,2.2 -v1 -v2 <(preprocess < file1) <(preprocess < file2)
address_3
        Bill_ID

答案2

假设,就像在您发布的示例输入中一样,同一个单词不会在两个输入文件中多次出现,然后在每个 Unix 机器上的任何 shell 中使用任何 awk:

$ cat tst.awk
BEGIN {
    OFS="\t"
    print ARGV[1], ARGV[2]
}
{ lc = tolower($1) }
NR==FNR {
    file1[lc] = $1
    next
}
lc in file1 {
    delete file1[lc]
    next
}
{
    print "", $1
}
END {
    for (lc in file1) {
        print file1[lc], ""
    }
}

$ awk -f tst.awk file1 file2
file1   file2
        Bill_ID
address_3

答案3

尝试这个awk。开箱即用,可处理任意数量的文件。

旁注:请小心space输入数据中单词末尾的 s。

$ awk '{ str=tolower($0); a[str]++; aa[str]=$0; b[str]=b[str]" "FILENAME } 
    END{ for(i in a){ if(a[i]==1){ print aa[i],b[i] } } }' file1 file2
address_3  file1
Bill_ID  file2

如果您想要类似表格的输出,请在前者中添加一个格式化 awk。结果已准备好复制粘贴到 Excel 等中。当然,字符串中的TABs 和,会弄乱格式。

$ awk '{ str=tolower($0); a[str]++; aa[str]=$0; b[str]=b[str]","FILENAME }
    END{ for(i in a){ if(a[i]==1){ print aa[i]b[i] } } }' file1 file2 |
  awk -F ',' '{ nm_a[$NF]++; a[$NF,nm_a[$NF]]=$1 } 
    END{ for(i in nm_a){ printf "%s\t",i; if(max<nm_a[i]){ max=nm_a[i] } }; 
    print "";  for(j=1;j<=max;j++){ for(i in nm_a){ printf "%s\t",a[i,j] } 
    print "" } }' 
file2   file1   
Bill_ID address_3

相关内容