
私のデータは複数の行にあり、それをタブで区切られた複数の列に置き換えたいと思います。
ABC 0.98 0.58 5.87 0.01
DEF 0.88 5.85 6.89 0.25
GHI 8.99 5.66 4.78 6.22
入力する
ABC DEF GHI
0.98 0.88 8.99
0.58 5.85 5.66
5.87 6.89 4.78
0.01 0.25 6.22
上記の形式で出力を取得できるように、この問題を解決するのに役立ちますか?
答え1
GNUの使用datamash
:
$ datamash -W transpose <file
ABC DEF GHI
0.98 0.88 8.99
0.58 5.85 5.66
5.87 6.89 4.78
0.01 0.25 6.22
datamash
これは、スペースで区切られた行をタブ区切りの列に置き換えるために使用されます。
このオプションを使用して他の出力区切り文字を設定できます--output-delimiter
。ここでは、予想される出力を再現するように見えるスペースを使用しました。
$ datamash -W --output-delimiter=' ' transpose <file
ABC DEF GHI
0.98 0.88 8.99
0.58 5.85 5.66
5.87 6.89 4.78
0.01 0.25 6.22
答え2
すべてのUnixシステムのすべてのシェルでawkを使用してください。
$ cat tst.awk
{
for ( rowNr=1; rowNr<=NF; rowNr++ ) {
vals[rowNr,NR] = $rowNr
}
}
END {
for ( rowNr=1; rowNr<=NF; rowNr++ ) {
for ( colNr=1; colNr<=NR; colNr++ ) {
printf "%s%s", vals[rowNr,colNr], (colNr<NR ? OFS : ORS)
}
}
}
$ awk -f tst.awk file
ABC DEF GHI
0.98 0.88 8.99
0.58 5.85 5.66
5.87 6.89 4.78
0.01 0.25 6.22
次のコマンドを使用すると、上記の作業をより簡単に実行できます。
$ cat tst.awk
{
for ( rowNr=1; rowNr<=NF; rowNr++ ) {
vals[rowNr] = (rowNr in vals ? vals[rowNr] OFS : "") $rowNr
}
}
END {
for ( rowNr=1; rowNr<=NF; rowNr++ ) {
print vals[rowNr]
}
}
$ awk -f tst.awk file
ABC DEF GHI
0.98 0.88 8.99
0.58 5.85 5.66
5.87 6.89 4.78
0.01 0.25 6.22
ただし、この場合、同じ変数に新しい値を継続的に再割り当てすることに注意してください。vals[rowNr]
これはawkが何を必要とするかを決定する必要があるため、新しい変数ごとに一度割り当てるよりもawkの操作が比較的遅いです。どのくらいのメモリが必要ですか?新しい値を保存するには、古い値を新しいメモリ位置に移動し、新しい値を追加してから古い位置を解放します。これにより、多くの小さなチャンクの代わりにいくつかの大きなメモリチャンクが必要になるため、awkは見つけるのが難しくなります。変数がサイズに応じて増加するため、メモリを解放します。また、出力形式と入力読み取りを混在させるので、生成されたコードは最初のスクリプトよりも密接に結合されます。しかし、それはひどいものではありません。少なくともコードは簡単です。
答え3
BSD操作のように聞こえますrs
(1983年以降はBSDに含まれていましたが、通常は他のシステムにはデフォルトではインストールされません)。
$ cat file
ABC 0.98 0.58 5.87 0.01
DEF 0.88 5.85 6.89 0.25
GHI 8.99 5.66 4.78 6.22
$ rs -T < file
ABC DEF GHI
0.98 0.88 8.99
0.58 5.85 5.66
5.87 6.89 4.78
0.01 0.25 6.22
答え4
使用幸せ(以前のPerl_6)
raku -e '.put for [Z] lines.map(*.words);'
または(ステップ2):
raku -e 'my @a = lines.map(*.words); .put for [Z] @a;'
入力例:
ABC 0.98 0.58 5.87 0.01
DEF 0.88 5.85 6.89 0.25
GHI 8.99 5.66 4.78 6.22
出力例:
ABC DEF GHI
0.98 0.88 8.99
0.58 5.85 5.66
5.87 6.89 4.78
0.01 0.25 6.22
2番目の例を簡単に説明するために、配列をlines
読み取り、@a
各配列をスペースで区切られたwords
(たとえば、列)に分割します。 2番目のステートメントでは、データはoutput
ですが[Z]
、zipなどの縮小演算子を使用して最初の配列要素の最初の単語を取得し、2番目の配列要素の最初の単語と3番目の配列要素の最初の単語を返します。一緒に
または、CSV / TSVの要件がより厳しい場合は、Text::CSV
コマンドラインからRakuモジュールを使用できます。
~$ raku -MText::CSV -e '.put for [Z] csv(in => $*IN, sep => " ");' < file
ABC DEF GHI
0.98 0.88 8.99
0.58 5.85 5.66
5.87 6.89 4.78
0.01 0.25 6.22
https://docs.raku.org/言語/operators#index-entry-[]_(reduction_metaoperators)
https://unix.stackexchange.com/a/670344/227738
https://raku.org