I need to compare 2 files and print matched lines.
If file1 username is in file2 (field 1) I want to print it to new matched file.
File1.txt:
Hey123
Johnson
Hanny123
Fanny
(file1 is 240MB – 20.000.000 lines)
File2.txt:
Gromy123:hannibal
Hey123:groll
Hanny123:tronda9
Kroppsk:football23
(file2 is 1.4GB – 69.000.000 lines)
Expected matched lines output:
Hanny123:tronda9
Hey123:groll
I have been trying for 4 hours without success. Both the files are sorted and I have tried join + countless of grep / awk commands. My big problem is RAM exhaustion. Would love some help how I could approach this, so large files.
Best Answer
If the files are sorted (the samples you posted are) then it's as simple as
join
pairs up lines from two files where the join field is equal. By default, the join field is the first field, the fields are output in order except that the join field is not repeated, and non-pairable lines are skipped, which is exactly what you want.Note that if the files have Windows line endings, they appear under Unix systems to have an extra carriage return character at the end of each line. The CR is mostly visually invisible, but as far as
join
and other text tools are concerned, it's a character like any one else, and it means the fields ofFile1.txt
all end with a CR whereas the ones inFile2.txt
don't so they don't match. You need to strip the CR, at least inFile1.txt
.You do need to sort the files. If they aren't, then ksh/bash/zsh, you can use process substitutions. (Add
tr -d '\r' |
if needed.)In plain sh, if your Unix variant has
/dev/fd
(most do), you can use that instead to pipe the output of two programs through two file descriptors.If you need to preserve the original order of
File1.txt
and it isn't sorted by the join field, then add line numbers to remember the original order, sort by the join field, join, sort by line numbers and strip the line numbers. (You can do something similar if you want to preserver the order of the other file.)