여러 하위 행 항목(열)이 있는 CSV를 Awk의 새 열로 변환하는 방법은 무엇입니까?

여러 하위 행 항목(열)이 있는 CSV를 Awk의 새 열로 변환하는 방법은 무엇입니까?

아래 표시된 일반 형식의 CSV 파일이 있습니다.

이 CSV에는 특정 열( desc)에 속하는 여러 행이 있으며 이러한 항목을 추출하여 추가하고 싶습니다.새로운열은 name, size, weight, glass각각 호출됩니다. 항목의 하위 항목을 빨간색으로 강조 표시했습니다.

원래 구조:

여기에 이미지 설명을 입력하세요.

예상되는 구조:

여기에 이미지 설명을 입력하세요.


원본 CSV:

page,item,id,desc,price
1,2,F1,Alpha,111.11
1,,,380 x 2280 mm (size),
1,,,Weight: 33.0 kg,
1,,,Glass: AAA,
1,,,XXX,
1,3,F2,Beta,222.22
1,,,880 x 2280 mm (size),
1,,,Weight: 68.4 kg,
1,,,Glass: BBB,
1,,,YYY,
1,4,F3,Gamma,333.33
1,,,1980 x 1580 mm (size),
1,,,Weight: 78.2 kg,
1,,,Glass: CCC,
1,,,XXX,
1,,,YYY,
1,,,ZZZ,

예상되는 생성된 CSV:

page,item,id,name,size,weight,glass,price
1,2,F1,Alpha,380 x 2280,33.0,AAA,111.11
1,3,F2,Beta,880 x 2280,68.4,BBB,222.22
1,4,F3,Gamma,1980 x 1580,78.2,CCC,333.33

어디이름첫 번째 행을 대체합니다설명하다.


고쳐 쓰다:

특정 조건에서 일부 Awk 솔루션은 위와 같이 작동하지만 네 번째 항목을 추가하면 실패합니다. 철저한 테스트를 위해 위에 다음을 추가하는 것을 고려해보세요.

1,7,F4,Delta,111.11
1,,,11 x 22 mm (size),
1,,,Weight: 33.0 kg,
1,,,Glass: DDD,
1,,,Random-1,

따라서 3가지 주요 사항은 다음과 같습니다.

  • 열의 하위 행 수는 desc다양할 수 있습니다.
  • 이후의 모든 하위 줄은 Glass:...무시되어야 합니다.
  • 이있을 수 있습니다프로젝트전혀지항열 내에서도 desc무시되어야 합니다.

Q: 다음을 사용하여 이러한 하위 행을 새 열로 다시 매핑하려면 어떻게 해야 합니까??
(또는 bash에서 이 작업을 수행하는 데 더 적합한 도구가 있습니까?)

아마도 관련이 있지만 별로 도움이 되지 않는 질문:

답변1

awk 'BEGIN{ FS=OFS=","; print "page,item,id,name,size,weight,glass,price" }
    $2!=""{ price=$5; data=$1 FS $2 FS $3 FS $4; desc=""; c=0; next }
          { gsub(/ ?(mm \(size\)|Weight:|kg|Glass:) ?/, "") }
    ++c<=3{ desc=(desc==""?"":desc OFS) $4; next }
    data  { print data, desc, price; data="" }
' infile

설명 포함:

awk 'BEGIN{ FS=OFS=","; print "page,item,id,name,size,weight,glass,price" }
     #this block will be executed only once before reading any line, and does: 
            #set FS (Field Separator), OFS (Output Field Separator) to a comma character
            #print the "header" line  ....

    $2!=""{ price=$5; data=$1 FS $2 FS $3 FS $4; desc=""; c=0; next }
    #this blocks will be executed only when column#2 value was not empty, and does:
            #backup column#5 into "price" variable
            #also backup columns#1~4 into "data" variable
            #reset the "desc" variable and also counter variable "c"
            #then read next line and skip processing the rest of the code 

          { gsub(/ ?(mm \(size\)|Weight:|kg|Glass:) ?/, "") }
            #this block runs for every line and replace strings above with empty string

    ++c<=3{ desc=(desc==""?"":desc OFS) $4; next }
    #this block runs at most 3reps and 
           #joining the descriptions in column#4 of every line
           #and read the next line until counter var "c" has value <=3 

     data { print data, desc, price; data="" }
     #if "data" variable has containing any data, then
           #print the data, desc, price and empty "data" variable 
' infile 

관련 정보