このパターンに似たテキスト行がたくさんあります。値と名前を1つの行にグループ化できますか?
ABCDEFG_10_node10:2154 ABCDEFG_10_node10:54
ABCDEFG_10_node10:2254 ABCDEFG_10_node10:64
ABCDEFG_10_node10:410 ABCDEFG_10_node10:10
ABCDEFG_10_node10:210 ABCDEFG_10_node10:10
ABCDEFG_10_node10:365
ABCDEFG_10_node10:890
ABCDEFG_10_node10:741
XXYZZ_71_node2:24: XXYZZ_71_node2:504:
X3y5z_53_node1:664: X3y5z_53_node1:990:
RCTY_11_node2:224: RCTY_11_node2:234:
予想出力:
ABCDEFG_10_node10: 2154,2254,410,210,365,890,741,54,64,10,10
XXYZZ_71_node2: 24,504
X3y5z_53_node1: 664,990
RCTY_11_node2: 224,234
私はAIXを使用しています。どうすればいいですか?
答え1
Perlアプローチ(順序は重要ではないと仮定):
$ perl -lne 'while(/(\w+):(\d+)/g){
push @{$k{$1}},$2
}
END{
print "$_: " . join ",", @{$k{$_}} for keys %k
}' file
ABCDEFG_10_node10: 2154,54,2254,64,410,10,210,10,365,890,741
入力ファイルを 1 行ずつ読み込み、-ln
で提供されたスクリプトを実行します-e
。空でないすべてのインスタンスがwhile(/(\w+):(\d+)/g)
収集され、空で:
ないインスタンスがさらに収集されます。かっこ内に含まれているのでこれが$1
名前と$2
値になります。その後、%k
値が配列であるハッシュ配列にプッシュされます。最後に、ハッシュの各キー(名前)とその値の配列を印刷して渡します,
。
簡潔さを重視する場合は、上記の内容を1行で書くことができます。
perl -lne 'while(/(\S+):(\S+)/g){push @{$k{$1}},$2}}{$"=",";print"$_: @{$k{$_}}" for keys%k' file
読みやすさを超えて:
perl -nE'push@{$k{$1}},$2while/(\w+):(\d+)/g}{$"=",";say"$_: @{$k{$_}}"for keys%k' file
答え2
アッ解決策:
awk -F':|[[:space:]]+' '{
a[$1]=a[$1]? a[$1]","$2:$2; if(NF==4) b[$3]=b[$3]? b[$3]","$4:$4
}
END{ for(i in a) printf "%s: %s%s\n",i,a[i],(i in b)? ","b[i]:"" }' file
-F':|[[:space:]]+'
- 複雑なフィールド区切り記号a[$1]=a[$1]? a[$1]","$2:$2
- 各識別名のグループ値ABCDEFG...
if(NF==4) b[$3]=b[$3]? b[$3]","$4:$4
- 追加の右側の部分がある場合 - 値を追加の配列にグループ化します。b
出力:
ABCDEFG_10_node10: 2154,2254,410,210,365,890,741,54,64,10
----------
値の順序が重要でない場合は、上記の方法を少し単純化できます。
awk -F':|[[:space:]]+' '{
a[$1]=a[$1]? a[$1]","$2:$2; if(NF==4) a[$3]=a[$3]? a[$3]","$4:$4
}
END{ for(i in a) print i":",a[i] }' file
答え3
awk '{ for (i=1;i<=NF;i++) { split($NF,arr,":");if (dat[arr[1]]=="") { dat[arr[1]]=arr[2] } else { dat[arr[1]]=dat[arr[1]]","arr[2] } } } END { for ( i in dat ) { print i": "dat[i] } }' filename
Romanのもう1つのawkソリューションは、スペースで区切られた各データを順番に取得し、配列arrの分割関数を使用して文字に基づいてデータをさらに分割します。次に、文字列を使用してABCなどの文字列をキーとして配列を作成します。印刷します。次に、この配列を繰り返し、キー、:、および文字列で始まる文字列を作成します。その後、印刷してください。
答え4
Raku(以前のPerl_6)の使用
raku -e 'say .key, " => ", .value.words[1,3,5...*] for lines.split(/<[:\s]>/, :skip-empty).rotor(2).classify( *.[0]);'
入力例:
ABCDEFG_10_node10:2154 ABCDEFG_10_node10:54
ABCDEFG_10_node10:2254 ABCDEFG_10_node10:64
ABCDEFG_10_node10:410 ABCDEFG_10_node10:10
ABCDEFG_10_node10:210 ABCDEFG_10_node10:10
ABCDEFG_10_node10:365
ABCDEFG_10_node10:890
ABCDEFG_10_node10:741
XXYZZ_71_node2:24: XXYZZ_71_node2:504:
X3y5z_53_node1:664: X3y5z_53_node1:990:
RCTY_11_node2:224: RCTY_11_node2:234:
出力例:
XXYZZ_71_node2 => (24 504)
RCTY_11_node2 => (224 234)
ABCDEFG_10_node10 => (2154 54 2254 64 410 10 210 10 365 890 741)
X3y5z_53_node1 => (664 990)
つまり、lines
読み取り、破壊的にsplit
読み取り(空の要素を省略して:
)、2つの要素ごとに(接続)し、各ペアの最初の要素を通じて-ingします。 [意図を明確にするために電話をすることもできましたが、とにかく楽は正しいことをしました。]\s
:skip-empty
rotor
classify
.classify( *.[0].unique)
OPが自分の投稿で指定した形式を本当に望む場合は、=>
通話の終わりに通話を置き換えて追加します:
。したがって、前の部分全体は次のようになります。join
.value
for
say .key, ": ", .value.words[1,3,5...*].join(",")
出力例(2):
X3y5z_53_node1: 664,990
RCTY_11_node2: 224,234
ABCDEFG_10_node10: 2154,54,2254,64,410,10,210,10,365,890,741
XXYZZ_71_node2: 24,504