Registros empilhados em colunas

0

Tenha um arquivo como este:

1
2
3
     # always a double newline
a
b
c     # each subgroup has the same number of rows

9
10

y
z
...

É basicamente column1, seguido por uma nova linha dupla, depois pela coluna dois, por uma nova linha dupla e de volta à coluna1

Não faça suposições sobre a natureza dos valores (eles poderiam ser qualquer coisa), ou o número de "colunas" (poderia ser 2 ou 3, embora conhecido antecipadamente)

Esperando por um resultado como este:

1,a
2,b
3,c
9,y
10,z
...

Qual é a ferramenta certa para o trabalho?

    
por Neil McGuigan 28.01.2017 / 02:07

4 respostas

3

Outra solução usando awk e bash :

paste -d, <(awk -v RS='\n\n' 'NR%2' file) <(awk -v RS='\n\n' '!(NR%2)' file)

Isso leva em conta apenas linhas vazias como separadores, linhas não vazias podem ser qualquer coisa.

    
por 28.01.2017 / 18:19
2

Uma solução rápida com seu arquivo de entrada de amostra (copio / colo seus dados de entrada em um arquivo local chamado c2.txt). Ele não foi testado sob todas as condições para possíveis falhas, mas você pode tentar ver se o resultado satisfaz você.

$ paste -d"," <(grep -E '[0-9]' c2.txt) <(grep -E '[a-z]' c2.txt)
1,a
2,b
3,c
9,y
10,z

Na verdade, eu uso o mesmo arquivo duas vezes. Um para números um para strings e colar os une.

    
por 28.01.2017 / 02:21
1

Que tal usar o awk no modo de parágrafo; dividindo cada registro ímpar em uma matriz indexada e, em seguida, fazendo um loop através dele usando os índices do seguinte registro par:

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

O uso de um separador de campo de nova linha torna mais seguro a entrada mais geral, por exemplo dado file2

foo
bar
baz bar

a
b
c

9
10

hello world
z

então

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
    
por 28.01.2017 / 03:01
0

Script do Python 2

Como o OP solicitou que os valores de entrada possam ser qualquer coisa e apenas o dobro da nova linha pode ser usado como guia em comentários , aqui está uma versão alternativa do script (o original pode ser encontrado no histórico de edição desta resposta), usando o arquivo de entrada do steeldriver para testes:

#!/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)

Execução de teste:

$ 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
    
por 28.01.2017 / 03:43