n개 파일의 통신

n개 파일의 통신

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 ""
}

관련 정보