用于改进命令打印匹配和不匹配情况的awk:

用于改进命令打印匹配和不匹配情况的awk:,awk,Awk,是否要读取并比较两个文件中的第一个字段,然后打印 匹配两个文件中的行-(在f11.txt和f22.txt中提供)->Op_Match.txt 非匹配行来自f11.txt(在f11.txt中可用,在f22.txt中不可用)->Op_NonMatch_f11.txt 来自f22.txt的非匹配行(在f22.txt中可用,在f11.txt中不可用)->Op_NonMatch_f22.txt 使用以下3个单独的命令来实现上述场景的功能 f11.txt 10,03-APR-14,abc 20,02-JUL

是否要读取并比较两个文件中的第一个字段,然后打印

  • 匹配两个文件中的行-(在f11.txt和f22.txt中提供)->Op_Match.txt
  • 非匹配行来自f11.txt(在f11.txt中可用,在f22.txt中不可用)->Op_NonMatch_f11.txt
  • 来自f22.txt的非匹配行(在f22.txt中可用,在f11.txt中不可用)->Op_NonMatch_f22.txt
  • 使用以下3个单独的命令来实现上述场景的功能

    f11.txt

    10,03-APR-14,abc
    20,02-JUL-13,def
    10,19-FEB-14,abc
    20,02-AUG-13,def
    10,22-JAN-07,abc
    10,29-JUN-07,abc
    40,11-SEP-13,ghi
    
    f22.txt

    50,DL,3000~4332,ABC~XYZ
    10,DL,5000~2503,ABC~XYZ
    30,AL,2000~2800,DEF~PQZ
    
    要匹配两个文件中的行,请执行以下操作:

    awk ' BEGIN {FS = OFS = ","} FNR==NR {a[$1] = $0; next} ($1 in a) {print $0,a[$1]}'   f22.txt f11.txt> Op_Match.txt
    
    10,03-APR-14,abc,10,DL,5000~2503,ABC~XYZ
    10,19-FEB-14,abc,10,DL,5000~2503,ABC~XYZ
    10,22-JAN-07,abc,10,DL,5000~2503,ABC~XYZ
    10,29-JUN-07,abc,10,DL,5000~2503,ABC~XYZ
    
    要从f11.txt中删除不匹配的行,请执行以下操作:

    awk ' BEGIN {FS = OFS = ","} FNR==NR {a[$1] = $0; next} !($1 in a) {print $0}'   f22.txt f11.txt > Op_NonMatch_f11.txt
    
    20,02-JUL-13,def
    20,02-AUG-13,def
    40,11-SEP-13,ghi
    
    要从f22.txt中删除不匹配的行,请执行以下操作:

    awk ' BEGIN {FS = OFS = ","} FNR==NR {a[$1] = $0; next} !($1 in a) {print $0}'   f11.txt f22.txt > Op_NonMatch_f22.txt
    
    50,DL,3000~4332,ABC~XYZ
    30,AL,2000~2800,DEF~PQZ
    

    使用上述3个单独的命令来实现上述场景。有没有最简单的方法来避免3个不同的命令?任何建议

    类似的东西,未经测试:

    awk '
    BEGIN{ FS=OFS="," }
    NR==FNR {
        fname1 = FILENAME
        keys[NR] = $1
        recs[NR] = $0
        key2nrs[$1] = ($1 in key2nrs ? key2nrs[$1] RS : "") NR
        next
    }
    {
        if ($1 in key2nrs) {
            split (key2nrs[$1],nrs,RS)
            for (i=1; i in nrs; i++) {
                print recs[nrs[i]], $0 > "Op_Match.txt"
            }
            matched[$1]
        }
        else {
            print > ("Op_NonMatch_" FILENAME ".txt")
        }
    }
    END {
        for (i=1; i in recs; i++) {
            if (! (keys[i] in matched) ) {
                print recs[i] > ("Op_NonMatch_" fname1 ".txt")
            }
        }
    }
    ' f11.txt f22.txt
    
    此答案与Kent和Etans答案之间的主要区别在于,他们假设f22.txt中的$1只能在该文件中出现一次,而如果在f22.txt的多行上出现第一个字段,则上述方法可以工作

    另一个区别是,上面的输出行的顺序与它们在输入文件中出现的顺序相同,而其他答案将根据它们在哈希表中的内部存储方式以随机顺序输出其中一些行。

    这里有一个:

    awk -F, -v OFS="," 'NR==FNR{a[$1]=$0;next}
        $1 in a{print $0,a[$1]>("common.txt");c[$1];next} 
        {print $0>("NonMatchFromFile1.txt")}                     
        END{for(x in a)
            if(!(x in c)) 
                print a[x]>("NonMatchFromFile2.txt")}' f2 f1     
    

    有了这个,您将得到3个文件:
    common.txt、nonmatchfromFile1.txt和nonMatchfromfile2.txt

    我没有检查@EdMorton的答案,但他很可能答对了

    我的解决方案(乍看起来比他的略不一般)是:


    try comm comm不适用于行内的字段,只适用于整行。在看到OP的代码之前,我也一直在考虑这个问号(如果F22可以有dup行)。在看到您的答案F22.txt中可能没有重复的键值之前,我从未想过。我支持Kent。我只是假设手术的条件是对的,你可能是对的。通常由OPs发布的脚本是错误的,但idk如果是这样或不是这样的话。埃德·莫顿:哇,这是岩石,它正在按预期的方式工作,非常感谢您的良好支持!!!我认为你们的
    c[$1]
    人口的位置不对。您不需要在表示输出文件的字符串周围使用括号-您只需要在那里构造文件名时使用括号,例如通过连接。@EdMorton是的,您是对的,来自错误的编辑,我现在就把它修好了如果OP在f22中不能有dup键值,并且不关心在末尾部分输出的行的顺序,那么您和Kents的解决方案就可以很好地工作了。
    awk -F, '
    FNR==NR {
        a[$1]=$0;
        next
    }
    ($1 in a){
        print $0,a[$1] > "Op_Match.txt"
        am[$1]++
    }
    !($1 in a) {
        print $0 > "Op_NonMatch_f11.txt"
    }
    END {
        for (i in a) {
            if (!(i in am)) {
                print a[i] > "Op_NonMatch_f22.txt"
            }
        }
    }
    ' f22.txt f11.txt