두 번째 열을 기반으로 한 열을 병합합니다.

두 번째 열을 기반으로 한 열을 병합합니다.

내 파일은 다음과 같습니다.

pw1jc5ssyt6hx618,254343
ysezaratlycpuggl,254333
pht92h4adr3mrbz3,254343
hguvgstqxu3gowfg,254344
gqjp2rsjmk1a2v9c,254333
twdzyi2ddbnrfknd,254333
gcmj7krrx5x6nf8r,254341
tpqorqbyrg1nmm7s,254333
alnac47rt8d4ege3,254343

-두 번째 열을 기준으로 이 파일을 구분 기호로 병합하여 결과가 다음과 같도록 하고 싶습니다 .

254343,pw1jc5ssyt6hx618-pht92h4adr3mrbz3-alnac47rt8d4ege3
254333,ysezaratlycpuggl-gqjp2rsjmk1a2v9c-twdzyi2ddbnrfknd-tpqorqbyrg1nmm7s
254344,hguvgstqxu3gowfg
254341,gcmj7krrx5x6nf8r

답변1

awk당신의 친구입니다

$ cat 299360
ipw1jc5ssyt6hx618,254343
ysezaratlycpuggl,254333
pht92h4adr3mrbz3,254343
hguvgstqxu3gowfg,254344
gqjp2rsjmk1a2v9c,254333
twdzyi2ddbnrfknd,254333
gcmj7krrx5x6nf8r,254341
tpqorqbyrg1nmm7s,254333
alnac47rt8d4ege3,254343
$ awk -v FS="," '/^$/{next} # for empty line go to next record
                {if(NR==1){ # checking for first record
                f2[$2]=$1;next} # Adding $1 to array f2 at index $2
                else{
                if($2 in f2){ # Check if $2 is already an index in f2
                f2[$2]=f2[$2]"-"$1;next #appending "-$1" to current value
                }
                else{
                f2[$2]=$1;next
                }
                }}
                END{ # This line will be processed at the end
                for(i in f2){  # for all the indexes i in f2
                printf "%s,%s\n",i,f2[i] #printing in the desired format
                }
                }
                ' 299360
254341,gcmj7krrx5x6nf8r
254333,ysezaratlycpuggl-gqjp2rsjmk1a2v9c-twdzyi2ddbnrfknd-tpqorqbyrg1nmm7s
254343,pw1jc5ssyt6hx618-pht92h4adr3mrbz3-alnac47rt8d4ege3
254344,hguvgstqxu3gowfg

설명하다

  1. FS=","– FS는 awk의 내장 변수로 필드 구분자를 나타냅니다. 필드 구분 기호를 다음으로 설정하면 구분 기호로 ,설정됩니다 .,
  2. $1$2등을 통해 필드에 액세스 할 수 있습니다 .
  3. awk 스크립트는 작은따옴표로 묶입니다.'awk-script-goes-here'
  4. NR레코드 번호(현재 처리 중인 레코드 번호)를 나타내는 awk 내장 변수입니다. 기본적으로 각 행은 레코드입니다.
  5. field2로 색인된 연관 배열 (예: )을 f2[$2]=$1 설정하고 있습니다 .f2$2
  6. $2 in f2인덱스가 배열에 이미 존재하는지 확인하십시오.
  7. 그리고 자명 if-else하다 .printf
  8. awk의 블록은 END마지막에만 실행됩니다. 즉, 모든 레코드가 처리된 후에 실행됩니다.
  9. for(i in f2)awk에서 연관 배열을 구문 분석하는 데 사용되는 for 루프 구조입니다. 이것은 또 다른 표현으로,for every index i in f2 do something
  10. 위의 for루프는 배열을 순서대로 인쇄하지 않을 수 있습니다. 그러나 sortbash 명령을 사용하여 배열을 정렬할 수 있습니다.
  11. next후속 명령을 처리하지 않고 다음 레코드로 이동합니다.
  12. /pattern/awk의 패턴 확인; 패턴은 ^$빈 줄을 확인합니다.

인용하다

awk 전문가가 되고 싶다면,효과적인 awk 프로그래밍꼭 읽어야 할 책입니다.

추악한 한 줄짜리

awk -v FS="," '/^$/{next}{if(NR==1){f2[$2]=$1;next}else{if($2 in f2){f2[$2]=f2[$2]"-"$1;next}else{f2[$2]=$1;next}}}END{for(i in f2){printf "%s,%s\n",i,f2[i]}}' 299360

노트:이상적으로는 awk 스크립트에서 줄바꿈을 하드코딩하는 것은 좋지 않습니다 printf "%s,%s\n",i,f2[i]. printf "%s,%s\n",i,f2[i];print추가 이식성을 위해 .

답변2

GNU와 함께데이터 혼합:

datamash -t, -s -g 2 collapse 1 <data.txt | sed 's/,/-/2g'

결과:

254333,ysezaratlycpuggl-gqjp2rsjmk1a2v9c-twdzyi2ddbnrfknd-tpqorqbyrg1nmm7s
254341,gcmj7krrx5x6nf8r
254343,pw1jc5ssyt6hx618-pht92h4adr3mrbz3-alnac47rt8d4ege3
254344,hguvgstqxu3gowfg

답변3

존재하다 perl:

#! /usr/bin/perl

use strict;
my %mergecol = ();

while(<>) {
  s/#.*//;            # strip comments
  next if (m/^\s*$/); # skip empty lines
  chomp;
  my ($val,$key) = split ',';
  push @{ $mergecol{$key} }, $val;
};

foreach my $k (keys %mergecol) { 
  printf "%s,%s\n", $k, join('-', @{ $mergecol{$k} } );
}

while루프는 입력을 읽고 HoA(해시 배열) 구조, 즉 각 요소가 배열("목록"이라고도 함)인 연관 배열을 생성합니다. 해시의 키는 두 번째 필드이고, 각 목록의 요소는 동일한 두 번째 필드가 있는 행의 첫 번째 필드입니다.

스크립트 끝에서 각 레코드에 대해 키 이름, 쉼표, 를 포함하는 HoA 한 줄을 인쇄합니다 -.

다음으로 실행:

$ ./rock.pl rock.txt
254341,gcmj7krrx5x6nf8r
254333,ysezaratlycpuggl-gqjp2rsjmk1a2v9c-twdzyi2ddbnrfknd-tpqorqbyrg1nmm7s
254344,hguvgstqxu3gowfg
254343,pw1jc5ssyt6hx618-pht92h4adr3mrbz3-alnac47rt8d4ege3

또는 "한 줄"로 줄여서 셸 명령이나 스크립트에 포함합니다.

$ perl -n -e '
    s/#.*//;
    next if (m/^\s*$/);
    chomp; ($v,$k)=split ","; push @{ $mc{$k} }, $v;
    END {
     foreach $k (keys %mc) { printf "%s,%s\n", $k, join("-",@{$mc{$k}}) }
    }' rock.txt 

또는

$ perl -e 'while(<>) {s/#.*//;next if (m/^\s*$/);chomp;($v,$k)=split ",";push @{$mc{$k}}, $v};
    foreach $k (keys %mc) {printf "%s,%s\n",$k,join("-",@{$mc{$k}})}' rock.txt

해시 또는 연관 배열은 다음과 같습니다.본질적으로 무질서한, 출력을 정렬하려면 입력을 파이프하거나 sort위 줄을 사용하십시오.(sort keys %f)foreach my $k

답변4

GNU의 2차원 배열awk

awk -F, '{
  a[$2][$1]
  }
  END{
    for (i in a) {
      c=0; printf "%s,", i; 
        for (j in a[i]) {
          ++c; printf "%s%s", j, length(a[i]) == c? "\n": "-"
          }
     }
   }' file

관련 정보