2개의 파일 세트가 있습니다.
파일 1에는 다음 ID가 포함되어 있습니다.
1111
2222
6666
3333
4444
파일 2에는 ID와 사용자 이름이 포함되어 있습니다.
1873 Neil
1111 Roger
7632 Tim
3333 Oscar
8723 Greg
4444 Roy
6666 Patrick
ID와 사용자 이름을 추출하고 싶지만 파일 1의 ID와 동일한 항목만 추출하고 싶습니다. grep -f file1 file2
방금 게시한 것과 같이 ID가 거의 없는 상태에서 만든 두 개의 테스트 파일에 대해 정상적인 작업을 수행했습니다 . 그러나 이것을 두 개의 올바른 파일에 적용하면 file1에는 3500개의 ID가 있고 File2에는 12000개의 ID + 사용자 이름이 포함되어 있으며 두 파일에 나타나는 3500줄을 추출하는 대신 12000줄을 추출합니다. 그러나 2개의 테스트 파일과 일부 더미 ID를 사용하여 올바른 ID만 추출하고 나머지는 유지합니다.
무엇이 문제인지에 대한 조언이 있나요?
답변1
다음을 사용하여 이 작업을 수행해 보세요.가입하다대신 grep
, 이것이 더 적절할 것입니다:
$ join <(sort file1) <(sort file2)
1111 Roger
3333 Oscar
4444 Roy
6666 Patrick
쉘이 누락된 경우프로세스 교체 <( )
, 넌 할 수있어:
sort file1 > new_file1
sort file2 > new_file2
join new_file1 new_file2
의사는 이렇게 말했습니다.
Join은 동일한 조인 필드가 있는 각 입력 행 쌍을 표준 출력에 기록합니다.
바라보다http://www.gnu.org/software/coreutils/manual/html_node/join-inspiration.html
지침:
이것이 제대로 작동하려면 정렬 키를 기준으로 파일을 정렬해야 합니다 join
. 이것이 바로 우리가 일부를 사용하는 이유입니다.파일 설명자백그라운드에서 사용됨프로세스 교체
바라보다http://mywiki.wooledge.org/ProcessSubstitution, 또는http://mywiki.wooledge.org/BashFAQ/024일반적인 용도.
답변2
grep
사용자 이름과 ID가 동일한 행과 일치합니다. join
첫 번째 필드에 대한 일치를 올바르게 제한하지만 정렬된 입력이 필요합니다. 입력에 따라 awk
좋은 선택이 될 수 있습니다.
awk 'FNR == NR { ids[$1]++; next } ids[$1]' ids users
또는 더 읽기 쉽게 하려면:
awk 'FNR == NR { ids[$1]; next } $1 in ids' ids users
산출:
1111 Roger
3333 Oscar
4444 Roy
6666 Patrick
설명하다
awk 프로그램은 두 부분으로 나누어집니다: 첫 번째 파일을 평가하는 부분과 두 번째 파일을 평가하는 부분입니다.
첫 번째 블록은 첫 번째 파일에 대해서만 평가되며 ID를 ids
배열에 저장합니다. 읽는 동안 이러한 ID가 발견되면 users
기본 block()이 호출됩니다 {print $0}
.