Try the following generic solution for N files. It stores the data of the first file in a hash with a value of 1 , and for each hit from the following files, this value increases. At the end, I compare if the value of each key matches the number of processed files and prints only those that match.
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}
This gives:
"xxx" 0 "aba" 0
EDIT to add a version that prints the entire line (see comments). I added another array with the same key, where I save the string, and also use it in the printf function. I missed the old code.
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}
NEW EDIT (see comments) to add a version that processes multiple lines with the same key. Basically, I join all the records instead of saving only one, changing line[$1,$2] = $0 to line[$1,$2] = line[$1,$2] ( line[$1,$2] ? SUBSEP : "" ) $0 . During printing, I do the reverse separation with the delimiter ( SUBSEP variable) and print each entry.
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}
With the new data edited in question, it gives:
"xxx" 0 0 "aba" 0 0 "aba" 0 0 1