AWK를 사용하여 행이 거의 없는 열로 변환 [중복]

AWK를 사용하여 행이 거의 없는 열로 변환 [중복]

다음 내용이 포함된 텍스트 파일이 있습니다.

제목 1 A1
제목 3 A3
제목 4 A4
제목 5 A5

제목 1 B1
제목 2 B2
제목 5 B5

제목 1 C1
제목 2 C2
제목 4 C4
제목 5 C5

타이틀 1 D1
타이틀 2 D2
타이틀 3 D3

나는 다음과 같은 출력을 원합니다 :

title1      title2       title3        title4      title5  
  A1                        A3           A4          A5  
  B1           B2                                    B5  
  C1           C2                        C4          C5  
  D1           D2           D3                        

AWK를 사용하여 코드를 작성하는 방법을 알려주실 수 있나요?

미리 감사드립니다!

답변1

공백(또는 ":")만으로 구분되도록 데이터를 변경할 수 있는 경우 다음 awk 프로그램이 이를 수행할 수 있습니다. 레이아웃을 완벽하게 만들기 위해 조정해야 할 수도 있습니다.

BEGIN { i = 1; }
$1 != "" { C[$1] = $1; X[$1,i] = $2 ; next; }
{ i++; }
END {
    asort(C);
    for ( k in C ) printf "  %8s\t", C[k];
    printf "\n";
    for ( j = 1; j <= i; j++ ) {
        for ( k in C ) printf "%8s\t",X[C[k],j];
        printf "\n";
    }
}

답변2

awk -f  transpose_rows_to_cols.awk /tmp/1
title1  title2  title3  title4  title5
A1      A3  A4  A5
B1  B2          B5
C1  C2      C4  C5
D1  D2  D3      

추신. 터미널에서 포맷하면 됩니다.

스크립트 -

#!/usr/bin/awk -f
BEGIN {
    printf("title1\ttitle2\ttitle3\ttitle4\ttitle5\n");
    a["title1"] = a["title2"]= a["title3"]= a["title4"]= a["title5"] = ""
}
{
    if ($0 !~ /^$/) {
        if ($0 ~ /:/)  {FS=":"; $0=$0} else {FS=" "; $0=$0}
        a[$1]=$2
    } else {
        printf("%s\t%s\t%s\t%s\t%s\n", a["title1"], a["title2"], a["title3"], a["title4"], a["title5"])
        a["title1"] = a["title2"]= a["title3"]= a["title4"]= a["title5"] = ""
    }
}
END{
        printf("%s\t%s\t%s\t%s\t%s\n", a["title1"], a["title2"], a["title3"], a["title4"], a["title5"])
}

답변3

이 답변은 다음을 기반으로 합니다.Ralph Rehnquist의 답변, 하지만

  1. 열은 헤더별 알파벳 순서가 아닌 사용자가 지정한 순서로 출력되어야 한다고 가정합니다.
  2. 데이터 값은 여러 단어가 허용됩니다.

Ralph의 답변과 마찬가지로 제목이 콜론이 아닌 공백으로 데이터와 분리되어 있다고 가정합니다.

목표 1을 달성하려면 입력이 원하는 순서대로 모든 헤더(수반되는 데이터 없음)를 포함하는 섹션으로 시작해야 합니다.

BEGIN { i = 0; j= 0; }
$1 != "" { if (i==0) C[++j] = $1; else { label = $1; $1 = ""; X[label,i] = $0; } next; }
{ i++; }
END {
    for ( k in C ) printf "  %8s\t", C[k];
    printf "\n";
    for ( j = 1; j <= i; j++ ) {
        for ( k in C ) printf "%8s\t", X[C[k],j];
        printf "\n";
    }
}

i으로 초기화 0되고 해당 i==0사례는 특별히 처리됩니다. 헤더만 캡처되고(이것이 있어야 하는 유일한 것이므로) 헤더는 값이 아닌 C증분 정수( )로 인덱스된 배열에 저장됩니다. j헤더 자체의. 그렇지 않으면 데이터를 캡처합니다.  $1 = "";행의 첫 번째 필드를 제거하고 $0다른 모든 필드를 연결하여 다시 작성합니다. (이로 인해 필드 사이에 여러 공백이 손실됩니다. 이는 약간의 작업으로 수정될 수 있습니다.) 데이터 배열에 대한 인덱스로 사용할 수 있도록 값을 변수 $1에 저장합니다 .labelX

예를 들어 다음 입력은 다음과 같습니다.

name
address
phone
height
weight

name John Lennon
phone 123
height 6' 1"
weight 180

name Sir Paul M.
address Liverpool
weight 175

name George
address 42                 Main St.
height 71"
weight 185 lbs

name Ringo Starr
address Penny Lane
phone 456 789

다음 출력을 생성합니다.

      name         address           phone          height          weight
 John Lennon                         123           6' 1"             180
 Sir Paul M.     Liverpool                                           175
  George         42 Main St.                         71"         185 lbs
 Ringo Starr     Penny Lane      456 789

값이 15자 이상이면 해당 열이 꺼집니다. 이는 개선될 수 있습니다.

관련 정보