2017-10-05 2 views
3

첫 번째 열 $1을 기반으로 한 행을 병합하고 출력을 포맷하고 싶습니다. 헤더를 인쇄하는 동안 Max Unique count of first field. 을 생성해야합니다. 예를 들어, 앙골라는 count = 3, 브라질은 count = 5, 잠비아는 count = 1로 나타납니다. 필드 $ 1의 최대 고유 카운트는 5이므로 모든 필드에 대해 적절한 헤더를 갖기 위해 헤더를 5 번 인쇄해야합니다.awk가 열을 기준으로 행을 병합합니다.

출력을 인쇄하는 동안 original input file 라인 주문을 유지하고 싶습니다. 로 사용 내 실제 입력 파일이 Input.csv Output.csv

현재
Country,Network,Details,Amount,Country,Network,Details,Amount,Country,Network,Details,Amount,Country,Network,Details,Amount,Country,Network,Details,Amount 
Angola,voda,xxx,10,Angola,at&t,xxx,20,Angola,mtn,xxx,30 
Brazil,voda,yyy,40,Brazil,voda,yyy,50,Brazil,at&t,yyy,60,Brazil,mtn,yyy,70,Brazil,voda,yyy,80 
Zambia,tcl,zzz,90 

을 원하는

Country,Network,Details,Amount 
Angola,voda,xxx,10 
Angola,at&t,xxx,20 
Angola,mtn,xxx,30 
Brazil,voda,yyy,40 
Brazil,voda,yyy,50 
Brazil,at&t,yyy,60 
Brazil,mtn,yyy,70 
Brazil,voda,yyy,80 
Zambia,tcl,zzz,90 

10 개 필드, 12 개 필드 등

같은 차이가 나는 두 아래를 사용하고 있습니다 명령을 사용하여 원하는 출력을 얻고 실제 입력 파일의 필드 수에 따라 매번 수동으로 카운트를 변경하십시오.

단계 : # 1

awk 'BEGIN { while (count++<5) header=header "Country,Network,Details,Amount,"; print header }' > output.csv 

단계 : 2

awk -F, ' 
    /.+/{ 
     if (!($1 in Val)) { Key[++i] = $1; } 
     Val[$1] = Val[$1] $0 ","; 
    } 
    END{ 
     for (j = 1; j <= i; j++) { 
      print(Val[Key[j]]); 
     } 
    }' input.csv >> output.csv 

제안을 찾고 ...

+0

당신은 ++ OrderNum [$ 1] '와 같은 배열을 유지'와 외부 루프로 그를 추가하려면 END 인쇄 문을 구동하기 위해,하지만 왜는'AWK'{기존의 음식물을} '사용할 수 있습니다 | 정렬'(귀하의 입력 데이터가 국가 이름별로 정렬 된 것 같습니다)? 행운을 빕니다. – shellter

+0

그리고 ... 작은 샘플 데이터, 필요한 출력 및 ... 잘 쓰여진 Q에 대해 우노를 사용합니다. 계속 게시하고 행운을 빌어 요! – shellter

답변

4

awk 한 - 라이너 :

awk 'BEGIN{FS=OFS=","}FNR==1{n=$0;next}{a[$1]=($1 in a ? a[$1] OFS:"")$0; if(!($1 in b)){o[++i]=$1}; b[$1]++; mx=mx>b[$1]?mx:b[$1] }END{for(i=1; i<=mx; i++)printf("%s%s",n,i==mx?RS:OFS); for(i=1; i in o; i++)print a[o[i]]}' infile 

입력 :

$ cat infile 
Country,Network,Details,Amount 
Angola,voda,xxx,10 
Angola,at&t,xxx,20 
Angola,mtn,xxx,30 
Brazil,voda,yyy,40 
Brazil,voda,yyy,50 
Brazil,at&t,yyy,60 
Brazil,mtn,yyy,70 
Brazil,voda,yyy,80 
Zambia,tcl,zzz,90 

출력 :

$ awk 'BEGIN{FS=OFS=","}FNR==1{n=$0;next}{a[$1]=($1 in a ? a[$1] OFS:"")$0; if(!($1 in b)){o[++i]=$1}; b[$1]++; mx=mx>b[$1]?mx:b[$1] }END{for(i=1; i<=mx; i++)printf("%s%s",n,i==mx?RS:OFS); for(i=1; i in o; i++)print a[o[i]]}' infile 
Country,Network,Details,Amount,Country,Network,Details,Amount,Country,Network,Details,Amount,Country,Network,Details,Amount,Country,Network,Details,Amount 
Angola,voda,xxx,10,Angola,at&t,xxx,20,Angola,mtn,xxx,30 
Brazil,voda,yyy,40,Brazil,voda,yyy,50,Brazil,at&t,yyy,60,Brazil,mtn,yyy,70,Brazil,voda,yyy,80 
Zambia,tcl,zzz,90 

더 나은 읽을 수 :,864,475,524,920,663,210 코멘트

awk 'BEGIN{ 
      FS=OFS="," 
    } 
    FNR==1{ 
      n=$0; 
      next 
    } 
    { 
      a[$1]=($1 in a ? a[$1] OFS:"")$0; 
      if(!($1 in b)){ o[++i]=$1 }; 
      b[$1]++; 
      mx=mx>b[$1]?mx:b[$1] 
    } 
    END{ 
      for(i=1; i<=mx; i++) 
       printf("%s%s",n,i==mx?RS:OFS); 

      for(i=1; i in o; i++) 
       print a[o[i]] 
    }' infile 

: 어디 코드를 변경, 알고 출력은 처음 에서 "나라"를 인쇄하는 I가 필요하지 않은 경우

이 하시겠습니까 같은 나라 이름 2 시간, 세 번째 인쇄

$ awk 'BEGIN{FS=OFS=","}FNR==1{n=$0;next}{a[$1]=($1 in a ? a[$1] OFS substr($0,index($0,",")+1) : $0); if(!($1 in b)){o[++i]=$1}; b[$1]++; mx=mx>b[$1]?mx:b[$1] }END{for(i=1; i<=mx; i++)printf("%s%s",i==1?n:substr(n,index(n,",")+1),i==mx?RS:OFS); for(i=1; i in o; i++)print a[o[i]]}' infile 
Country,Network,Details,Amount,Network,Details,Amount,Network,Details,Amount,Network,Details,Amount,Network,Details,Amount 
Angola,voda,xxx,10,at&t,xxx,20,mtn,xxx,30 
Brazil,voda,yyy,40,voda,yyy,50,at&t,yyy,60,mtn,yyy,70,voda,yyy,80 
Zambia,tcl,zzz,90 

수정 된 코드 : 수정 관련

awk 'BEGIN{ 
      FS=OFS="," 
    } 
    FNR==1{ 
      n=$0; 
      next 
    } 
    { 
      # this line modified 
      # look for char pos of comma, 

      a[$1]=($1 in a ? a[$1] OFS substr($0,index($0,",")+1) : $0); 

      if(!($1 in b)){ o[++i]=$1 }; 

      b[$1]++; 
      mx=mx>b[$1]?mx:b[$1] 
    } 
    END{ 
      for(i=1; i<=mx; i++) 
       # this line modified 
       printf("%s%s",i==1?n:substr(n,index(n,",")+1),i==mx?RS:OFS); 

      for(i=1; i in o; i++) 
       print a[o[i]] 
    }' infile 

설명 : 찾을 문자열의 첫 번째 항목에 대한 문자열을 검색

  • index(in, find)

및 0에서 해당 어커런스가 시작되는 문자의 위치를 ​​반환합니다. 에서문자열. 문자열의 substr(string, start [, length ])

  • 반환 길이 문자 길이의 문자열, 문자 번호 시작에서 시작.

+0

감사합니다 Akshay Hegde, Up-voted !!! – SVR

+0

@RVS : 주문 번호가 –

+0

으로 업데이트되었습니다. 동일한 국가 이름을 두 번째로, 세 번째로 인쇄 할 필요가없는 경우 코드를 변경하여 처음으로 "국가"를 인쇄 할 때만 변경하십시오. – SVR

관련 문제