파일 간에 2개의 기본 열을 일치시키고 이러한 기본 열이 일치하면 추가 열을 출력 파일에 붙여넣습니다. 첫 번째 파일의 줄 크기를 일정하게 유지

파일 간에 2개의 기본 열을 일치시키고 이러한 기본 열이 일치하면 추가 열을 출력 파일에 붙여넣습니다. 첫 번째 파일의 줄 크기를 일정하게 유지

이것은 제가 약 24시간 전에 질문한 이전 질문에 대한 후속 답변입니다.파일 간의 기본 열을 모두 일치시키고 이러한 기본 열이 일치하면 출력 파일에 보조 열을 붙여넣습니다.

G-Man은 작동하는 코드로 이 문제를 해결했지만 후속 질문이 있습니다. 답변을 수락했으므로 두 번째 게시물은 다음과 같습니다.

3개의 파일이 있고 각 파일에는 고유한 수의 열이 있으며 모든 열은 탭으로 구분되어 있지만 일부 열은 3개의 파일 간에 공유됩니다. 이것은 일종의 "집계" 파일을 생성하는 데 사용하려는 3개 파일 간의 공유 열입니다.

다음 표에서는 이러한 파일의 예를 보여줍니다. 기본적으로 MAIN1과 MAIN2 열 사이의 파일을 일치시키고 싶습니다. 두 열 모두 세 파일 간에 일치해야 합니다.

두 파일 사이에 MAIN1과 MAIN2가 일치하는 경우 file2의 "minor8" 열을 file1의 테이블 오른쪽에 추가하고 싶습니다. 나중에 두 파일 사이에 MAIN1과 MAIN2가 일치하면 file3의 "minor9"를 file1 테이블 오른쪽에 추가하고 싶습니다. "minor8"은 file1의 가장 오른쪽 열(열 이름: "minor3") 옆에 있어야 하므로 새 출력 파일에서는 "minor9"가 "minor8" 옆에 있기를 원합니다. 출력 파일은 이상적인 최종 파일이 어떤 모습이어야 하는지에 대한 아이디어를 제공합니다.

기본적으로 다음은 3개 파일의 예입니다("탭"이 약간 혼란스럽습니다).

파일 1:

MAIN1   minor1  MAIN2   minor3
1  bla1    a    blabla1
1  bla2    b    blabla2
1  bla3    c    blabla3
2  bla4    a    blabla4
2  bla5    d    blabla5
3  bla6    e    blabla6
4  bla7    f    blabla7
5  bla8    a    blabla8
5  bla9    g    blabla9

파일 2:

minor8  MAIN1   MAIN2
yes1    2   d
yes2    3   e
yes3    4   f
yes4    5   a
yes5    5   g
yes6    1   a
yes7    1   b
yes8    1   c
yes9    2   a

파일 3:

MAIN1   MAIN2   minor9
5   a   sure1
5   g   sure2
1   a   sure3
1   b   sure4
1   c   sure5
2   a   sure6
2   d   sure7
3   e   sure8
4   f   sure9

필수 출력 파일:

MAIN1   minor1  MAIN2   minor3  minor8  minor9
1   bla1    a   blabla1 yes6    sure3
1   bla2    b   blabla2 yes7    sure4
1   bla3    c   blabla3 yes8    sure5
2   bla4    a   blabla4 yes9    sure6
2   bla5    d   blabla5 yes1    sure7
3   bla6    e   blabla6 yes2    sure8
4   bla7    f   blabla7 yes3    sure9
5   bla8    a   blabla8 yes4    sure1
5   bla9    g   blabla9 yes5    sure2

앞서 언급했듯이 G-Man은 내가 원하는 것을 정확하게 수행하는 유용한 코드를 제공합니다(이전 게시물 참조). 나는 G-Man(또는 시간이 있는 다른 사람)에게 내가 잘 이해하지 못하는 코드의 일부 개별 줄에 대해 몇 가지 구체적인 질문을 할 수도 있지만 그때까지는 후속 질문이 있습니다.

G-Man의 코드는 위의 OUTPUT 파일을 다시 생성할 수 있으므로 G-Man에게 감사드립니다!

후속 질문:

제가 언급하지 않은 한 가지는 코드가 실행되지 않고(제가 아는 한) MAIN1 및 MAIN2 열이 파일 간에 일치하지 않으면 file1에서 행을 삭제한다는 것입니다. 이것을 명시하지 않은 것은 내 잘못이다. 내 목표는 file1의 줄이 삭제되지 않는 출력 파일을 갖는 것입니다.

기본적으로 file1이 내 우선순위 파일입니다. 파일에 있는 줄 수(백만 개에 가까움)에 관계없이 이는 OUTPUT 파일에 있어야 하는 줄 수도 됩니다. MAIN1, MAIN2 열이 일치하지 않으면 일부 행의 "minor8" 및 "minor9" 열이 비어 있을 수 있습니다. 그러나 "minor8" 또는 "minor9"(또는 둘 다)에 대한 "누락/null" 값이 있는 경우 file1의 해당 행을 유지하고 싶습니다.

위의 파일 2와 3의 약간 다른 버전을 사용하여 이를 설명하려고 합니다(따라서 file1은 동일하게 유지됩니다).

조정된 파일 2(MAIN1, MAIN2 조합 없음: 2, d):

minor8  MAIN1   MAIN2
yes2    3   e
yes3    4   f
yes4    5   a
yes5    5   g
yes6    1   a
yes7    1   b
yes8    1   c
yes9    2   a

조정된 파일 3(MAIN1, MAIN2 조합 없음: 5, a):

MAIN1   MAIN2   minor9
5   g   sure2
1   a   sure3
1   b   sure4
1   c   sure5
2   a   sure6
2   d   sure7
3   e   sure8
4   f   sure9

원하는 출력을 조정했습니다(즉, MAIN1, MAIN2 조합 2-d의 경우 Minor8 열의 NULL, MAIN1, MAIN2 조합 5-a의 경우 Minor9 열의 NULL).

MAIN1   minor1  MAIN2   minor3  minor8  minor9
1   bla1    a   blabla1 yes6    sure3
1   bla2    b   blabla2 yes7    sure4
1   bla3    c   blabla3 yes8    sure5
2   bla4    a   blabla4 yes9    sure6
2   bla5    d   blabla5     sure7
3   bla6    e   blabla6 yes2    sure8
4   bla7    f   blabla7 yes3    sure9
5   bla8    a   blabla8 yes4    
5   bla9    g   blabla9 yes5    sure2

내가 설명하는 방식이 충분히 명확하기를 바랍니다. 나는 테이블의 탭이 약간 혼란스럽다고 생각한다. 이게 마음에 드시나요, 아니면 제가 시각적으로 테이블을 정리하는 걸 선호하시나요? (이로 인해 발생할 수 있다고 생각되는 유일한 문제는 예제 데이터를 복사하여 붙여넣을 때 거기에 없어야 할 추가 탭이 있다는 것입니다...)

어쨌든, 도와주셔서 정말 감사드립니다. 가까운 시일 내에 단순히 도움을 요청하는 것 이상으로 이 포럼에 기여할 수 있기를 바랍니다...

이를 가능하게 하기 위해 G-Man의 코드를 편집하는 방법에 대한 제안 사항이 있습니까? 또는 이러한 추가 요구 사항을 고려하여 유용한 코드를 작성하는 방법에 대해 완전히 다른 제안 사항이 있는 경우 알려 주시기 바랍니다.

답변1

다음 파일을 생성합니다:

merge21:

시작 {
        FS="\t"
        OFS = "\t"
}
NR==FNR { #파일 2
        키 =$2","$3
        존재[키] = 1
        작은 8[키] =1
        다음
}
{#파일 1
        키=$1 "," $3
        if (현재[키]) $1, $2, $3, $4,마이너 8 [키]
        그렇지 않으면 $1, $2, $3, $4, "-"를 인쇄합니다.
}

merge312:

시작 {
        FS="\t"
        OFS = "\t"
}
NR==FNR { #파일 3
        키 =$1","$2
        존재[키] = 1
        작은 9[키] =$3
        다음
}
{#파일 1 + 파일 2
        키=$1 "," $3
        if (현재[키]) $1, $2, $3, $4,$5, 미성년자 9 [열쇠]
        그렇지 않으면 $1, $2, $3, $4를 인쇄합니다.5달러, "-"
}

그것들은 거의 동일합니다. 차이점을 굵게 표시했습니다. 이제 명령을 입력하세요.

awk -f merge21 file2 file1 | awk -f merge312 file3 -

이는 키 필드에 쉼표가 포함되어 있지 않고 데이터에 하이픈이 포함되어 있지 않다고 가정하지만 실제로는 존재 여부에 따라 다릅니다.일부데이터에 나타나지 않는 문자열입니다. 더 많은 열을 지원하기 위해 이것을 확장하는 것은 쉽지 않습니다. 이것할 수 있다한 번에 모든 작업을 수행하도록 향상될 수 있지만 awk이는 좀 더 복잡하고 (IMNSHO) 노력할 가치가 없습니다.

이는 파일에 있는 데이터의 소위 "왼쪽 외부 조인"을 생성합니다.INNER 연결과 OUTER 연결의 차이점몇 가지 정의는 스택 오버플로를 확인하세요. ("왼쪽 외부 조인"은 이 질문에 대한 답변에서 "첫 번째 테이블의 모든 행과 다른 테이블의 공통 행"으로 정의(설명)됩니다.

귀하의 출력은 다음과 같습니다

MAIN1   minor1  MAIN2   minor3  minor8  minor9
1       bla1    a       blabla1 yes6    sure3
1       bla2    b       blabla2 yes7    sure4
1       bla3    c       blabla3 yes8    sure5
2       bla4    a       blabla4 yes9    sure6
2       bla5    d       blabla5 -       sure7
3       bla6    e       blabla6 yes2    sure8
4       bla7    f       blabla7 yes3    sure9
5       bla8    a       blabla8 yes4    -
5       bla9    g       blabla9 yes5    sure2

그리고 당연히 제거할 수도 있습니다.-문자 대 sed(물론 실제 데이터에 실제로 하이픈이 포함된 경우 누락된 데이터에 대한 자리 표시자로 사용되지 않은 문자나 문자열을 선택하십시오.)


노트

  • FSOFS는 각각 입력 필드 구분 기호와 출력 필드 구분 기호입니다. (분명히 IFS에서는 의미가 없습니다 awk. 그것은 제 실수였습니다.) 실제로는 필요하지 않을 것입니다 FS="\t". awk탭은 기본적으로 입력에서 필드 구분 기호로 인식됩니다. (공백을 포함하는 필드를 가질 수 있지만 그것에 관심이 없는 것 같습니다.)  OFS="\t"그래서 print $1, $2, $3, $4 입력 필드를 다음과 같이 말할 수 있습니다.산출그들 사이에 레이블이 있습니다. 라고 말하지 않으면 OFS="\t"공백으로 구분되므로 print $1 "\t" $2 "\t" $3 "\t" $4지루하고 가독성이 떨어집니다.
  • MAIN1 및 MAIN2에 추가 제약 조건을 부여한 경우(예를 들어 항상 하나의 문자이거나 MAIN1은 항상 숫자이고 MAIN2는 항상 문자로 시작함) ,()에 쉼표가 필요하지 않습니다 key. 그러나 첫 번째 질문의 원래 버전에는 그러한 제한이 표시되지 않았습니다. 다음 데이터를 고려하십시오.

    MAIN1 ($2)         MAIN2 ($3)         badkey = $2 $3         goodkey = $2 "," $3
        2              34151                  234151                   2,34151
       23               4151                  234151                   23,4151
    

    키 필드(MAIN1 및 MAIN2)에 표시되지 않는 일부 구분 기호를 키에 포함하지 않으면 key다른 행에 대해 동일한 값을 얻을 수 있습니다.

  • 트집을 잡을 위험이 있으므로 나는 Linux에게 아무 것도 "말"하지 않습니다. 단지 Linux에게 말하려고 할 뿐입니다. awk무엇을 해야할지 알려드립니다 .
  • 코드에 대하여
    NR==FNR { # 파일 3
            키=$1 "," $2
            존재[키] = 1
            작은 9[키] = $3
            다음
    }
    file3을 포함하는 일곱 번째에서 마지막 행을 고려하십시오 1 a sure3. 분명히 $1= 1, $2= a$3= 가 있으므로 = sure3입니다 .  내가 표시하기 위해 플래그 로 설정했음을 의미합니다.key1,apresent[key] = 1present["1,a"]1file3 가지다1,a, =에는 minor9값이 있습니다. 줄이 없으므로 아무 것도 설정되지 않으므로 코드의 "" 부분은 =에 대한 내용이 없다는 것을 알고 인쇄해야 합니다.key1,a5,afile3present["5,a"]file1 + file2minor9key5,a-대신에. 이름은 present제가 임의로 선택한 것입니다 1,a.전시하다file3 ( 행은 아님) 입니다 5,a. 1표현하려면 "TRUE"를 사용하는 것이 일반적입니다 .
  • print $1, $2, $3, $4 로 바꿀 수 있습니다 . for (n=1; n<=4; n++) printf "%s\t", $n마지막 필드에 print 일반(대신)을 사용하거나 다음을 수행하여 줄을 끝내야 합니다. 다음과 같은 작업을 수행하여 더욱 단순화할 수 있습니다.printfprintf "\n"

            for (n=1; n<=4; n++) printf "%s\t", $n
            if (현재[키]) major8[키]를 인쇄합니다.
            그렇지 않으면 "-"를 인쇄합니다.

읽어주세요어크(1), 이것POSIX 사양awk, GNU Awk 사용자 가이드및 보기awk.info더 많은 정보를 알고 싶습니다.

관련 정보