在> 2个文件中查找常用元素

cha*_*has 7 awk compare

我有三个文件,如下所示

FILE1.TXT

"aba" 0 0 
"aba" 0 0 1
"abc" 0 1
"abd" 1 1 
"xxx" 0 0
Run Code Online (Sandbox Code Playgroud)

FILE2.TXT

"xyz" 0 0
"aba" 0 0 0 0
"aba" 0 0 0 1
"xxx" 0 0
"abc" 1 1
Run Code Online (Sandbox Code Playgroud)

file3.txt

"xyx" 0 0
"aba" 0 0 
"aba" 0 1 0
"xxx" 0 0 0 1
"abc" 1 1
Run Code Online (Sandbox Code Playgroud)

我想基于前两列找到所有三个文件中的类似元素.为了找到两个文件中的类似元素,我使用了类似的东西

awk 'FNR==NR{a[$1,$2]++;next}a[$1,$2]' file1.txt file2.txt 
Run Code Online (Sandbox Code Playgroud)

但是,当输入文件超过2时,我们怎样才能在所有文件中找到类似的元素?有人可以帮忙吗?

使用当前的awk解决方案,输出会忽略重复的键列并将输出作为

"xxx" 0 0
Run Code Online (Sandbox Code Playgroud)

如果我们假设输出来自file1.txt,则预期输出为:

"aba" 0 0 
"aba" 0 0 1
"xxx" 0 0 
Run Code Online (Sandbox Code Playgroud)

即它应该获得具有重复键列的行.

Bir*_*rei 3

尝试以下针对N 个文件通用的解决方案。它将第一个文件的数据保存在值为 的哈希中1,并且对于下一个文件的每次命中,该值都会递增。最后,我比较每个键的值是否与处理的文件数相同,并仅打印那些匹配的文件。

awk '
    FNR == NR { arr[$1,$2] = 1; next }
    { if ( arr[$1,$2] ) { arr[$1,$2]++ } }
    END { 
        for ( key in arr ) {
            if ( arr[key] != ARGC - 1 ) { continue }
            split( key, key_arr, SUBSEP )
            printf "%s %s\n", key_arr[1], key_arr[2] 
        } 
    }
' file{1..3}
Run Code Online (Sandbox Code Playgroud)

它产生:

"xxx" 0
"aba" 0
Run Code Online (Sandbox Code Playgroud)

编辑以添加打印整行的版本(请参阅注释)。我添加了另一个具有相同键的数组,用于保存该行,并在函数中使用它printf。我对旧代码留下了评论。

awk '
    ##FNR == NR { arr[$1,$2] = 1; next }
    FNR == NR { arr[$1,$2] = 1; line[$1,$2] = $0; next }
    { if ( arr[$1,$2] ) { arr[$1,$2]++ } }
    END { 
        for ( key in arr ) {
            if ( arr[key] != ARGC - 1 ) { continue }
            ##split( key, key_arr, SUBSEP )
            ##printf "%s %s\n", key_arr[1], key_arr[2] 
            printf "%s\n", line[ key ] 
        } 
    }
' file{1..3}
Run Code Online (Sandbox Code Playgroud)

新编辑(参见评论)添加一个使用相同键处理多行的版本。基本上我加入了所有条目,而不是只保存一个,line[$1,$2] = $0line[$1,$2] = line[$1,$2] ( line[$1,$2] ? SUBSEP : "" ) $0. 在打印时,我使用分隔符(SUBSEP变量)进行反向分割并打印每个条目。

awk '
    FNR == NR { 
        arr[$1,$2] = 1
        line[$1,$2] = line[$1,$2] ( line[$1,$2] ? SUBSEP : "" ) $0
        next
    }
    FNR == 1 { delete found }
    { if ( arr[$1,$2] && ! found[$1,$2] ) { arr[$1,$2]++; found[$1,$2] = 1 } }
    END { 
        num_files = ARGC -1 
        for ( key in arr ) {
            if ( arr[key] < num_files ) { continue }
            split( line[ key ], line_arr, SUBSEP )
            for ( i = 1; i <= length( line_arr ); i++ ) { 
                printf "%s\n", line_arr[ i ]
            } 
        } 
    }
' file{1..3}
Run Code Online (Sandbox Code Playgroud)

编辑有问题的新数据后,会产生:

"xxx" 0 0
"aba" 0 0 
"aba" 0 0 1
Run Code Online (Sandbox Code Playgroud)