2番目の列に基づいて列をマージします。

2番目の列に基づいて列をマージします。

私のファイルは次のとおりです。

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

-2番目の列に基づいてこのファイルを区切り記号にマージして、結果を次のようにしたいと思います。

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(ハッシュ配列)構造、つまり各要素が配列(「リスト」とも呼ばれる)である連想配列を生成します。ハッシュのキーは2番目のフィールドであり、各リストの要素は同じ2番目のフィールドを持つ行の最初のフィールドです。

スクリプトの最後に、各レコードのキー名、コンマ、およびを含むHoAの1行を印刷します-

次に実行:

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

または、「1行」に減らして、シェルコマンドまたはスクリプトに含めます。

$ 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

関連情報