n개(즉, 2개 이상) 파일에 대한 통신 기능을 찾고 있습니다.
man comm
내용은 다음과 같습니다.
COMM(1)
NAME
comm - compare two sorted files line by line
SYNOPSIS
comm [OPTION]... FILE1 FILE2
DESCRIPTION
Compare sorted files FILE1 and FILE2 line by line.
With no options, produce three-column output.
Column one contains lines unique to FILE1,
column two contains lines unique to FILE2,
and column three contains lines common to both files.
이 아이디어를 설명하기 위해 Bash에서 최적화되지 않은 최초의 다른 형식의 방식은 다음과 같습니다.
user@host MINGW64 dir
$ ls
abc ac ad bca bcd
user@host MINGW64 dir
$ tail -n +1 *
==> abc <==
a
b
c
==> ac <==
a
c
==> ad <==
a
d
==> bca <==
b
c
a
==> bcd <==
b
c
d
user@host MINGW64 dir
$ bat otherdir/ncomm.sh
───────┬───────────────────────────────────────────────────────────────────────
│ File: otherdir/ncomm.sh
───────┼───────────────────────────────────────────────────────────────────────
1 │ #!/usr/bin/env bash
2 │ ALLENTRIES=$(sort -u "$@")
3 │ echo "all $*" | tr " " "\t"
4 │
5 │ for entry in $ALLENTRIES; do
6 │ >&2 echo -en "${entry}\t"
7 │ for file in "$@"; do
8 │ foundentry=$(grep "$entry" "$file")
9 │ echo -en "${foundentry}\t"
10 │ done
11 │ echo -en "\n"
12 │ done
───────┴───────────────────────────────────────────────────────────────────────
user@host MINGW64 dir
$ time otherdir/ncomm.sh *
all abc ac ad bca bcd
a a a a a
b b b b
c c c c c
d d d
real 0m12.921s
user 0m0.579s
sys 0m4.586s
user@host MINGW64 dir
$
그러면 열 헤더가 stderr에 표시됩니다. 첫 번째 열 "all"에는 두 파일 중 하나(정렬됨)에서 발견된 모든 항목이 포함되고, 인수 목록의 파일당 하나의 열이 해당 행에 해당 항목과 함께 표시됩니다. grep은 첫 번째 열과 행을 넘어서는 모든 셀에 대해 한 번씩 호출되는데, 이는 정말 느립니다.
comm의 경우 이 출력은 id와 같은 짧은 줄/항목에만 적용됩니다. 더 깔끔한 버전은 2+ 열에 있는 각 항목에 대해 x 또는 이와 유사한 것을 출력합니다.
이는 Windows MSYS2의 Git 및 RHEL에서 작동합니다.
이를 보다 효율적인 방법으로 어떻게 달성할 수 있습니까?
답변1
meld
(그러나 그래픽 프로그램입니다.) 파일 간의 3방향 비교(예: n=3)를 관리하는 것은 여전히 가능하지만 더 큰 파일의 경우 이를 구현하는 것이 점점 계산적으로 복잡해지기 때문에 그렇지 diff
(또는 ) 도구"입니다.comm
답변2
다음 방법을 시도해 볼 수 있습니다. 다음과 같은 특징이 있습니다.
- 출력은 귀하의 예를 정확하게 따릅니다.
- 처리 중에 값이 정렬됩니다.
- => 사전 정렬은 건너뛸 수 있습니다.
- => 원래 주문은 유지되지 않습니다
- 입력 파일 이름이 정렬됩니다.
- 중복 값이 정리되고 병합되어 한 번만 표시됩니다(따라서 중복 값으로 이상한 동작을 보이는 스크립트의 버그도 수정되었습니다).
- 내장된 배열 정렬 기능을 사용하므로 최신 GNU AWK가 필요합니다.
- UNIX 줄 끝마무리에 맞게 맞춤화되어 다양한 줄 끝 스타일을 혼합하면 이상한 효과가 발생할 수 있습니다. (프로그램의 경우 "
a
"와 "a\r
"는 다릅니다!)
코드를 텍스트 파일에 저장하고 실행 권한을 제공하면 이를 쉘 스크립트의 드롭인 대체품으로 사용할 수 있습니다. 처리 속도가 향상될 것입니다. (실제로는 몇 배나 됩니다.) :)
#!/usr/bin/gawk -f
{
all[$0]
filenames[FILENAME]
input[$0,FILENAME]=$0
# if you only wanted to to mark existence
# then uncomment the following line
# input[$0,FILENAME]="*"
}
END {
PROCINFO["sorted_in"]="@ind_str_asc"
printf "all"
for (i in filenames) {
printf("\t%s",i)
}
for (i in all) {
printf("\n%s",i)
for (j in filenames) {
printf("\t%s",input[i,j])
}
}
print ""
}