![将记录堆叠到列中](https://linux22.com/image/104142/%E5%B0%86%E8%AE%B0%E5%BD%95%E5%A0%86%E5%8F%A0%E5%88%B0%E5%88%97%E4%B8%AD.png)
有一个这样的文件:
1
2
3
# always a double newline
a
b
c # each subgroup has the same number of rows
9
10
y
z
...
基本上是第 1 列,后跟双换行符,然后是第二列,双换行符,然后回到第 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
实际上我 grep 同一个文件两次。一个用于字符串,一个用于将它们粘贴在一起。
答案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