Unix 추출에서 두 TSV를 비교하고 키와 헤더의 차이를 인쇄하는 방법은 무엇입니까?

Unix 추출에서 두 TSV를 비교하고 키와 헤더의 차이를 인쇄하는 방법은 무엇입니까?

제목과 구조가 동일한 두 개의 파일이 있는데 첫 번째 열이 키입니다.

파일 1:

key    val1 val2 val3 val4 val5
Item1  10   12   44   88   22
Item2  33   33   43   77   22
Item3  28   44   55   22   11
Item4  12   55   55   14   44

파일 2:

key    val1 val2 val3 val4 val5
Item1  10   11   44   99   22
Item2  33   33   43   77   22
Item3  28   44   55   22   11
Item4  12   55   55   14   00

위 파일에서 알 수 있듯이 두 파일은 두 가지 측면에서 다릅니다.

  • item1의 val2와 val4가 다릅니다.
  • 항목 4의 val5가 다릅니다.

그래서 어떤 항목의 어떤 필드가 다른지 알려주는 비교 출력을 생성하고 싶습니다. 출력은 다음과 유사해야 합니다.

Item1: val2,val4
Item4: val5

답변1

awk -v ref=file1 '
    {
        getline refline <ref

        if (NR == 1) split(refline, head)

        nf = split(refline, a)

        for (i = 1; i <= nf; ++i)
            if ($i != a[i])
                diffcol[++n] = i

        if (n > 0) {
            $0 = a[1]

            for (i = 1; i <= n; ++i)
                $(i+1) = head[diffcol[i]]

            print
            n = 0
        }
    }' file2

그러면 파일이 file2'참조 파일'과 비교됩니다 file1. from 의 행 file2은 일반적으로 에 의해 읽혀지는 반면 from 의 행은 awk코드에서 호출 및 분할을 통해 file1명시적으로 읽혀집니다 .getlineawksplit

split(refline, head)블록은 배열을 head헤더로 설정하고 에서 읽습니다 file1. 이는 의 입력 첫 번째 줄에서만 수행됩니다 file2.

첫 번째 루프는 두 파일 간의 필드와 diffcol다르며 배열에 추가된 필드의 열 번호를 비교합니다.

하나 이상의 차이점이 발견되면 첫 번째 필드가 출력되고 그 뒤에 file1다른 필드(from)의 헤더가 출력됩니다.file1

코드를 작성한 방식, 헤더 행 및 첫 번째 필드도 비교 대상이므로 첫 번째 필드에서 차이점이 발견되면 아마도 key해당 행의 시작 부분에 출력 라인도 표시됩니다. 첫 번째 필드 값 file1).

코드에서는 두 파일의 열 수가 동일하다고 가정하지 않습니다.

질문의 데이터가 주어지면 이 코드에서 다음과 같은 출력을 얻을 수 있습니다.

Item1 val2 val4
Item4 val5

답변2

pasteawk모든 레코드에 동일한 수의 필드가 있다고 가정하고 및 의 조합을 사용하십시오 .

paste file1 file2 |
  awk -F'\t' '
    NR == 1 {cols = split($0, hdr) / 2; next}
    {
      diff = sep = ""
      for (i = 2; i <= cols; i++)
        if ($i "" != $(i+cols) "") {
          diff = diff sep hdr[i]
          sep = ","
        }
      if (sep) print $1": "diff
    }'

비교가 항상 어휘적( like or , from , 1e500 등)이 되도록 ""비교의 각 측면에 추가합니다 . 필드가 숫자처럼 보이는 경우 해당 필드를 제거하여 숫자로 비교할 수 있습니다.!=000-0infinfinity

관련 정보