以下の入力ファイルがあります。 o / pが述べたように、テキスト形式を再指定する必要があります。私はこのフォーラムで得られたawkを使用していますが、リストAの列番号に基づいています。助けてください
awk 'BEGIN{ max=0 }
/^List/{ if(k && k>max) { max=k; idx=c } ++c; k=0 }
NF{ a[c][++k]=$0 }
END{
for(i=1;i<=max;i++)
for(j=1;j<=c;j++) printf "%s%s",a[j][i],(j==c)?ORS:"\t"
}' filename | column -ts$'\t'
入力する:-
List A
Hello
how are you
fine
List B
good: Fine_health
hello: world_free
some: unkon_text
some: unkon_text1
some: unkon_text2
期待される出力
List A List B
Hello good: Fine_health
how are you hello: world_free
fine some: unkon_text
some: unkon_text1
some: unkon_text2
答え1
使用幸せ(以前のPerl_6)
~$ raku -e 'my @a = slurp.split("\n\n"); @a.=map(*.split("\n", :skip-empty)); \
my $length = @a>>.elems.max; for ^$length -> $i { \
print ($_[$i] // q[ ]) ~ q[|] for @a; "".say; \
};' filename.txt | column -ts'|'
上記の答えはRakuでコーディングされました。行はslurp
(一度読み取る)とsplit
段落(\n\n
)で構成されています。段落は配列に割り当てられます@a
。次の文では、各段落要素が行\n
で区切られています。max
配列の要素の長さを計算します。elems
@a
@a
その後、配列の各位置(読み取り:段落)print
が最大maxとしてエクスポートされ、$length
各位置(読み取り:行)の子要素が定義されていない(//
"define or"演算子を使用して)、スペースがq[ ]
挿入されました( "プレースホルダ" "文字"列)。列は~
末尾の|
列に関連付けられ、各行は終了します(改行文字を使用"".say;
)。
OPに必要な出力を提供するために、Unixユーティリティをcolumn
使用して挿入された|
バー区切り文字の列を分割します。 Raku専用ソリューションの場合、置き換えるとタブ区切りの出力が~ q[|]
返されます。~ qb[\t]
入力例:
List A
Hello
how are you
fine
List B
good: Fine_health
hello: world_free
some: unkon_text
some: unkon_text1
some: unkon_text2
出力例:
List A List B
Hello good: Fine_health
how are you hello: world_free
fine some: unkon_text
some: unkon_text1
some: unkon_text2
答え2
入力と出力の例は、両方のリストをリンクしようとしていることを意味します。これを行うためにawkは必要ありません。入力ファイルをlistとlistbの2つに分割し、貼り付けコマンドを使用してリンクします。
paste lista listb
入力ファイルを自動的に2つのファイルに分割し(各部分が1つまたは2つの空行で区切られていると仮定して)、空白のRSオプションでawkを使用できます。
awk -v RS= '{print > ("list" NR ".txt")}' listall
これにより、list1.txt および list2.txt ファイルが生成されます。
それから:
paste list1.txt list2.txt
答え3
公開されたスクリプトはいいえ働く最初の4行だけを印刷します。リストBの最後の2行は省略される。
問題は、k
各リストの行数を数えることです。しかし、それはmax
次にのみ保存されます。スタート各リストの長さなので、2番目のリストの長さは考慮されません。
回避策は、if(k && k>max) { max=k; }
最後のリストを読んだ後、ENDブロックの最初の行に繰り返すことです。
これは別のエラーを明らかにします。最後の 2 行は列にリストされず、列 1 に表示されます。問題は、column
長さ0の最初の列が認識されないようです。.
各値の先頭に a を強制的に適用すると、列に B が正しくリストされます。
個人的に私はawkで劣化したいです。各列の項目の最大長を保存し、%-*s
幅指定子で区切ります。おそらく、これは未使用の変数idx
の目的です。
編集:はい、明らかに列の間違いです。このタブは作業用ですFour
が、無視用ではありませんThree
。
先行および反復区切り文字をサポートするオプションがありますが、-n
Debian拡張で文書化されています(そして私のMint(Ubuntu)ディストリビューションでも動作します)。そうでない場合、-n
null値は削除され(つまり、最初の行と最後の行の区切り文字は無視され)、隣接する複数の区切り文字がマージされます。
$ cat -vet foo
One$
Two$
^IThree$
q^IFour$
$ column -t -s $'\t' foo | cat -vet
One$
Two$
Three$
q Four$
編集2:このバージョンにはより多くの機能があります。
(a)内部的にテーブル作成を実行してコマンドエラーを回避しますcolumn
(また、データセット全体をメモリに格納するためのawkと列の追加プロセスとメモリのオーバーヘッドを防ぎます)。
(b)複数のファイル引数を受け入れます(デフォルトでは標準入力なのでパイプラインで動作します)。
(c) 2 つではなく、必要な数の出力列で動作します。
(d)元のリリースのバグを修正しました(最も右側の列の長さは無視されました)。
#! /bin/bash
Awk='
BEGIN { Gap = 2; }
/^List/ { ++col; row=0; }
NF { X[++row, col] = $0;
if (mxrow < row) mxrow = row;
if (len[col] < length($0)) len[col] = length($0);
}
function Column (Local, r, c) {
for (r = 1; r <= mxrow; ++r) {
for (c = 1; c < col; ++c)
printf ("%-*s", Gap + len[c], X[r,c]);
printf ("%-s\n", X[r,c]);
}
}
END { Column( ); }
'
awk "${Awk}" "${@:-}"