단일 열이 있는 행을 한 행의 최대 4개 열에 결합하는 방법은 무엇입니까?

단일 열이 있는 행을 한 행의 최대 4개 열에 결합하는 방법은 무엇입니까?

아래와 같은 파일이 있습니다.

1 
4 5 6 7 19
20
22
24 26 27 
29
30
31
32 
34 
40 
50 
56 
58
100
234 235 270 500
1234 1235 1236 1237
2300
2303
2304
2307
2309

분명히 알 수 있듯이 1개 이상의 열이 있는 행도 있고 단일 열만 있는 행도 있습니다. 결합된 각 행에 최대 4개의 열이 있도록 단일 열 행을 결합하고 싶습니다. 따라서 출력은 다음과 같아야 합니다.

1  
4 5 6 7 19
20 22
24 26 27 
29 30 31 32
34 40 50 56 
58 100
234 235 270 500
1234 1235 1236 1237
2300 2303 2304 2307
2309

실제 데이터가 크다는 점을 고려하여 이를 수행하는 방법에 대한 제안이 있습니까?

답변1

약간 관용적이지만 gnu awk로 작업합니다.

awk '{printf "%s",(NF==1?$0 FS:(c==0?"":RS) $0 RS)} \
{(NF==1?++c:c=0)} \
c==4{printf "\n";c=0} \
END{printf "\n"}' file

#Output
1 
4 5 6 7 19
20 22 
24 26 27
29 30 31 32 
34 40 50 56 
58 100 
234 235 270 500
1234 1235 1236 1237
2300 2303 2304 2307 
2309 

설명:
awk 변수:
NF=필드 수
FS=필드 구분 기호 = 기본적으로 공백
RS=레코드 구분 기호= 기본적으로 새 줄.
c=카운터

1호선: {printf "%s",(NF==1?$0 FS:(c==0?"":RS) $0 RS)}: 중첩된 삼항 if 연산

#Single ternary if operation:
condition?true action:false action
#Nested if operations:  
condition1?true action 1:(condition2:true action2:false action2) #nested ternary if operations   
-------------------------[            ^ false action1 ^        ]   

이는 다음과 같은 의사 코드로 설명할 수 있습니다.

if NF==1 then print $0 and print FS   
else (if c==0 then print "" else print RS) and print $0 and print RS again   

2호선: {(NF==1?++c:c=0)}: 다음과 같이 표현될 수 있는 또 다른 삼항 if 연산:

If NF==1 (line has one field) 
then increase counter c by one 
else reset counter c.  

3호선 : c==4{printf "\n";c=0}클래식 awk 구문 :condition{action}

If counter c==4 then print a new line and reset counter c

4행: END{printf "\n"}' file: 스크립트 끝에 새 줄을 인쇄합니다.

답변2

sed원하는 것을 얻기 위해 다음을 사용할 수 있습니다 .

sed -e '
   /./!b
   /[^[:space:]]/!b
   /[^[:space:]][[:blank:]]\{1,\}[^[:space:]]/b

   :loop
      $q;N
      /\n.*\S[[:blank:]]\+\S/b
      s/\n/ /;tdummy
      :dummy
      s/[[:space:]]\{1,\}/&/3;t
   bloop
' yourfile


설명

  • NF > 1인 빈 줄, 공백 및 줄을 건너뜁니다.
  • 패턴 공간이 단일 필드 라인을 보유하는 지점에 do-while 루프를 설정하십시오.
  • 다음 줄을 잡고 NF > 1인지 확인합니다. 이 시점에서 전체 패턴 공간을 인쇄하고 다음 줄 읽기로 돌아갑니다.
  • 이제 우리는 다음 줄도 단일 필드라는 것을 알고 있으므로 패턴 공간에서 이 두 부분을 연결하는 줄바꿈을 자릅니다.
  • 패턴 공간에 아직 3개의 공간 청크가 있나요? 그렇다면 패턴 공간 전체를 인쇄하고 다음 줄을 읽기 시작합니다.
  • 그렇지 않으면 루프로 다시 분기하여 다음 줄을 읽지만 이를 기존 패턴 공간에 연결합니다.

결과

1
4 5 6 7 19
20 22
24 26 27
29 30 31 32
34 40 50 56
58 100
234 235 270 500
1234 1235 1236 1237
2300 2303 2304 2307
2309

답변3

용법: ./join_rows.awk input.txt

시스템에 따라 위치가 다를 수 있으므로 #!/usr/bin/awk -fshebang 을 확인하세요 .awk

#!/usr/bin/awk -f

BEGIN {
    count = 1;
}

{
    if (NF == 1) {
        if (count > 1 && count <= 4) printf " ";

        printf "%s", $1;
        count++;

        if (count > 4) {
            printf "\n";
            count = 1;
        }
    } else {
        if (count > 1) printf "\n";

        print;
        count = 1;
    }
}

END {
    if(count > 1) printf "\n";
}

산출:

1
4 5 6 7 19
20 22 
24 26 27  
29 30 31 32
34 40 50 56
58 100
234 235 270 500
1234 1235 1236 1237 
2300 2303 2304 2307
2309

답변4

펼친둔한 사람접근하다:

재배열_열.awk스크립트:

#!/bin/awk -f
function printRow(a, i, v)
{
    for (i in a) {
        printf "%s ", a[i]
    }
   print ""
   delete a
}
NF <= 2{
    for (i=1; i<=NF; i++) { 
        a[++c] = $i 
        if (length(a) == 4) {
            c = 0 
            printRow(a) 
        }
    }
}
NF > 2{
    if (length(a) > 0) {
        c = 0
        printRow(a)
    }
    print $0 
}
END{ print }

용법:

awk -f rearrange_columns.awk yourfile

출력:

1 
4 5 6 7 19
20 22 
24 26 27 
29 30 31 32 
34 40 50 56 
58 100 
234 235 270 500
1234 1235 1236 1237
2300 2303 2304 2307 
2309

관련 정보