두 파일을 비교하고 일치하는 줄을 인쇄해야 합니다. file1 사용자 이름이 file2(필드 1)에 있으면 이를 일치하는 새 파일에 인쇄하고 싶습니다.
파일 1.txt:
Hey123
Johnson
Hanny123
Fanny
(파일 1은 240MB - 20.000.000줄)
파일 2.txt:
Gromy123:hannibal
Hey123:groll
Hanny123:tronda9
Kroppsk:football23
(파일 2는 1.4GB - 69.000.000줄)
예상되는 일치 라인 출력:
Hanny123:tronda9
Hey123:groll
4시간 동안 노력했지만 성공하지 못했습니다. 두 파일 모두 정렬되어 있으며 Join + 수많은 grep/awk 명령을 시도했습니다. 내 가장 큰 문제는 메모리가 부족하다는 것입니다. 이렇게 큰 파일을 어떻게 처리할 수 있는지 도움을 받고 싶습니다.
답변1
파일이 정렬되어 있으면(게시한 예는 다음과 같습니다) 간단합니다.
join -t : File1.txt File2.txt
join
결합 필드가 동일한 두 파일의 행을 쌍으로 만듭니다. 기본적으로 조인 필드는 첫 번째 필드입니다. 단, 조인 필드가 반복되지 않고 필드가 순서대로 출력되며 페어링할 수 없는 행을 건너뛰는 것이 바로 원하는 것입니다.
파일이 있는 경우 참고하세요.Windows 라인 종결자, 각 줄 끝에 추가 캐리지 리턴이 있는 Unix 시스템에 나타납니다. CR은 대부분 시각적으로 보이지 않지만 join
다른 텍스트 도구에 관한 한 다른 문자와 같습니다. 즉, 모든 필드는 File1.txt
CR로 끝나지만 의 필드는 File2.txt
그렇지 않으므로 일치하지 않습니다. 적어도 에서는 CR을 삭제해야 합니다 File1.txt
.
<File1.txt tr -d '\r' | join -t : - File2.txt
파일을 정렬해야합니다. 그렇지 않은 경우 ksh/bash/zsh에서 프로세스 대체를 사용할 수 있습니다. (필요하다면 추가하세요 tr -d '\r' |
.)
join -t : <(sort File1.txt) <(sort File2.txt)
일반 sh에서 Unix 변형이 있는 경우 /dev/fd
(대부분 그렇습니다) 이를 사용하여 두 개의 파일 설명자를 통해 두 프로그램의 출력을 파이프할 수 있습니다.
sort File2.txt | { sort File1.txt | join -t : /dev/fd/0 /dev/fd/3; } 3<&1
원래 순서를 유지해야 File1.txt
하고 조인 필드별로 정렬하지 않는 경우 원래 순서를 기억하도록 줄 번호를 추가하고, 조인 필드별로 정렬하고, 조인하고, 줄 번호별로 정렬하고, 줄 번호를 제거합니다. (다른 파일의 순서를 유지하려면 비슷한 작업을 수행할 수 있습니다.)
<File1.txt nl -s : |
sort -t : -k 2 |
join -t : -1 2 - <(sort File2.txt) |
sort -t : -k 2,2n |
cut -d : -f 1,3
답변2
2GB의 RAM을 사용할 수 있다면 시도해 보세요.
awk -F: 'NR==FNR { n[$0]++ ; next}; $1 in n ' file1 file2 > file3
답변3
가능한 해결책(이것은 작은 예에서는 확실히 작동합니다):
#!/bin/bash
# because File2.txt is bigger, it gets the main loop.
# read each line of File2.txt
while read string; do
# read each line of File1.txt
while read string2; do
# check match, and write if needed.
if [[ $string == *"$string2"* ]]; then
echo $string >> match_output.txt
echo "wrote "$string" to match_output.txt..."
fi
done < File1.txt
done < File2.txt