次のファイルがあります。
1
2
3
# always a double newline
a
b
c # each subgroup has the same number of rows
9
10
y
z
...
デフォルトでは、列1、二重改行、列2、二重改行、再び列1
値の性質(何でも構いません)または「列」の数(あらかじめ知られていますが、2または3です)を想定しないでください。
次の出力が出ることが予想されます。
1,a
2,b
3,c
9,y
10,z
...
仕事に適したツールは何ですか?
答え1
awk
とを使用する別の解決策は次のとおりbash
です。
paste -d, <(awk -v RS='\n\n' 'NR%2' file) <(awk -v RS='\n\n' '!(NR%2)' file)
これは空行だけを区切り文字と見なし、空でない行は何でも構いません。
答え2
サンプル入力ファイルを使用したクイックソリューション(入力データをc2.txtというローカルファイルにコピーして貼り付けました)。すべての条件で可能なエラーをテストするわけではありませんが、試してみて結果が満足できることを確認できます。
$ paste -d"," <(grep -E '[0-9]' c2.txt) <(grep -E '[a-z]' c2.txt)
1,a
2,b
3,c
9,y
10,z
実際に同じファイルを2回grepします。 1つは文字列用で、もう1つは文字列を貼り付けるためのものです。
答え3
短絡モードでawkを使用するにはどうですか?各奇数レコードをインデックス配列に分割し、偶数レコードの次のインデックスを使用して繰り返します。
awk -vRS= -F'\n' '
NR%2 {split($0,a); next} {for (i=1;i<=NF;i++) print a[i],$i}
' OFS=, file
1,a
2,b
3,c
9,y
10,z
与えられた入力など、より一般的な入力には改行フィールド区切り文字を使用するのが安全です。file2
foo
bar
baz bar
a
b
c
9
10
hello world
z
それから
awk -vRS= -F'\n' '
NR%2 {split($0,a); next} {for (i=1;i<=NF;i++) print a[i],$i}
' OFS=, file2
foo,a
bar,b
baz bar,c
9,hello world
10,z
答え4
Python 2スクリプト
OPは入力値が何であっても二重改行のみをガイドとして使用するように要求したためコメント以下は、steeldriverの入力ファイルを使用してテストされたスクリプトの代替バージョンです(元のバージョンはこの回答の編集履歴にあります)。
#!/usr/bin/env python
from __future__ import print_function
import sys
columns = []
counter = 0
def print_columns(cols):
half = len(cols)/2
print("\n".join([ x+","+y for x,y in zip(cols[0:half],cols[half:]) ]))
with open(sys.argv[1]) as fd:
for line in fd:
if line.strip() == '':
counter+=1
continue
if counter >0 and counter%4 == 0:
print_columns(columns)
columns = []
counter = 0
columns.append(line.strip())
print_columns(columns)
テスト実行:
$ cat input.txt
foo
bar
baz bar
a
b
c
9
10
hello world
z
$ ./columnate_file.py input.txt
foo,a
bar,b
baz bar,c
9,hello world
10,z