如何在unix中检查2个CSV文件之间的标题?

如何在unix中检查2个CSV文件之间的标题?
File1 - filename.csv
File2 - filename.csv

我想使用 ksh 脚本比较 Linux 中这两个文件之间的标头。

情况1:-

比如说,file1的头是INPUT -->

NAME,UNIT CODE, VAR
JAMES01,IPU UNIT,OTHER
FIERCY,AUTOIMMUNE,OTHER

file2的头是INPUT -->

输出:- 这两个文件之间的标头匹配

案例2:-

假设 file1 的标头是 INPUT --> plant,animal,object file2 的标头是 INPUT --> plant,animal,object,tree

输出 - 有一个多余的列,EXCESS COLUMN NAME IS 'tree'

仅供参考 - 请注意标头是从 csv 文件中获取的,而不是硬编码的。非常感谢!

答案1

最简单的方法就是比较每个文件的第一行,然后根据它们是否相同移动到正确的目录:

$ diff -qs <(head -n1 file1.csv) <(head -n1 file2.csv) 
Files /dev/fd/63 and /dev/fd/62 differ

然后,您可以根据结果使用&&(和)和||(或)运算符对文件执行不同的操作。例如,如果file2.csv具有相同的标头,则将其移动到名为 的目录same,如果不同,则移动到名为 的目录different

$ mkdir -p same different
$ diff -qs <(head -n1 file1.csv) <(head -n1 file2.csv) && 
   mv file2.csv same/ || mv file2.cxv different/

如果您确实需要知道不同的特定字段,并且可以确定差异始终是最后一个字段,您可以这样做:

diff -qs <(head -n1 file1.csv) <(head -n1 file2.csv) >/dev/null && 
   echo "The headers are the same" ||
   echo "file2.csv has an extra entry: $(awk -F, '{ print $NF; exit}' file2.csv)"

如果您需要处理任何区别,使用:

awk -F, 'BEGIN{ FS=OFS="," }
       { 
        if(NR==FNR){ 
          for(i=1; i<=NF; i++){ a[$i]++ }
        }
        else{ 
         for(i=1; i<=NF; i++){ 
          if (! ($i in a)){
            b[$i]++
          }
         }
        }
       }
       END{ 
            printf "The second file has extra fields: ";
            for( field in b){
                printf "\"%s\" ", field
           }
       }' file1.csv file2.csv

答案2

这可能是您想要做的,未经测试并使用支持的 awk nextfile,例如 GNU awk:

awk '
    BEGIN { FS="," }
    FILENAME == ARGV[1] {
        nf = split($0,a)
        nextfile
    }
    FILENAME == ARGV[2] {
        nf = (NF > nf ? NF : nf)
        for ( i=1; i<=nf; i++ ) {
            if ( $i"" != a[i]"" ) {
                printf "Field %d difference: %s \"%s\" != %s \"%s\"\n", i, ARGV[1], a[i], FILENAME, $i
            }
        }
        exit
    }
' file1.csv file2.csv

如果你的 awk 不支持nextfile,请更改:

    FILENAME == ARGV[1] {
        nf = split($0,a)
        nextfile
    }

对此:

    FILENAME == ARGV[1] {
        if ( NR == 1 ) {
            nf = split($0,a)
        }
        next
    }

它仍然可以工作,只是运行速度较慢,因为它必须读取整个第一个文件,而不仅仅是它的第一行。

上面假设第二个文件不为空。如果可以,则在该FILENAME == ARGV[2]位置填充第二个数组,然后在该END部分中比较它们。

相关内容