Transformando texto em tabular

2

Eu tenho um arquivo de texto com a seguinte estrutura:

aaa
bbb
ccc
ddd
eee
fff

1
2
3
4
5
6

1.1
1.2
1.3
1.4
1.5
1.6

ggg
hhh
iii
jjj
kkk
lll

7
8
9
10
11
12

2.1
2.2
2.3
2.4
2.5
2.6

e quero a seguinte estrutura tabular:

aaa    1    1.1
bbb    2    1.2
ccc    3    1.3
ddd    4    1.4
eee    5    1.5
fff    6    1.6
ggg    7    2.1
hhh    8    2.2
iii    9    2.3
jjj    10   2.4
kkk    11   2.5
lll    12   2.6

Neste exemplo, cada coluna repete o padrão 2 vezes, mas o arquivo real faz isso mais vezes e tem mais campos.

    
por Msegade 30.08.2013 / 19:11

4 respostas

9

paste deve ser capaz de fazer o trabalho. Aqui x.1 é o nome do arquivo

paste <(grep -E '^[[:alpha:]]+$' x.1) \
      <(grep -E '^[[:digit:]]+$' x.1) \
      <(grep -E '^[[:digit:]]+[.][[:digit:]]+$' x.1) 
    
por 30.08.2013 / 20:02
4

Você poderia fazer:

mkfifo 0 1 2
awk -v RS= '{print > NR%3}' < file & paste 1 2 0

Há potencial para deadlock se qualquer um dos parágrafos for maior que o buffer de pipe (64k no Linux).

    
por 30.08.2013 / 21:45
3

Considerando quatro tipos de dados - 1) alfabetos, 2) inteiros, 3) números de ponto flutuante e 4) alfanuméricos, o script awk a seguir faz o trabalho.

/^[a-zA-Z]+$/ {
    alphabets[ia++] = $1;
    n++;
}

/[a-zA-Z]+[0-9]+[a-zA-Z0-9]*/ || /[0-9]+[a-zA-Z]+[a-zA-Z0-9]*/ {
    alphanumerics[an++] = $1;
}

/[0-9]+[.][0-9]+/ {
    floats[f++] = $1;
}

/^[0-9]+$/ {
    integers[k++] = $1;
}    

END {
    for (i = 0; i < n; i++) {
        print alphabets[i], integers[i], floats[i], alphanumerics[i];
    }
}

Salve o código acima em um arquivo, digamos, table.awk e execute como

awk -f table.awk input_text_file

Em particular, os blocos dos "tipos de dados" acima mencionados podem aparecer em qualquer ordem no arquivo de entrada. A saída obtida com os dados da amostra e seis valores alfanuméricos é a seguinte:

aaa 1 1.1 a1
bbb 2 1.2 b2
ccc 3 1.3 c3
ddd 4 1.4 d4
eee 5 1.5 e55
fff 6 1.6 6fF
ggg 7 2.1 
hhh 8 2.2 
iii 9 2.3 
jjj 10 2.4 
kkk 11 2.5 
lll 12 2.6 
    
por 30.08.2013 / 20:20
0

Usando uma única expressão TXR Lisp, baseada em um pipeline de funções de ordem superior e aplicação parcial, e uma string quase-mineral para formatar os campos de largura fixa:

$ txr -e '[(opip (partition* @1 (op where (op equal "")))
                 (tuples 3)
                 (reduce-left (op mapcar append))
                 (apply mapdo (op pprinl '@{1 6} @{2 6} @{3 6}')))
           (get-lines)]' < data
aaa    1      1.1
bbb    2      1.2
ccc    3      1.3
ddd    4      1.4
eee    5      1.5
fff    6      1.6
ggg    7      2.1
hhh    8      2.2
iii    9      2.3
jjj    10     2.4
kkk    11     2.5
lll    12     2.6

Como funciona

No geral, toda a expressão tem o formato [function argument] . O argument é (get-lines) , que snarfas linhas de um fluxo e retorna uma lista (lazy) de seqüências de caracteres. O fluxo é padronizado como *stdin* . O function é construído pela macro (opip ...) e é aí que toda a ação acontece.

Para entender opip , precisamos conhecer op , que opip usa implicitamente : significa " op pipeline "). Além disso, op é usado explicitamente em alguns lugares. Em suma, (op function args ...) é um acréscimo sintático para criar uma função anônima que chama function e cozinha alguns dos argumentos. Dentro de args ... , os argumentos da função anônima podem ser referenciados por número. A função anônima também implicitamente leva argumentos à direita. Por exemplo, (op + 3) denota uma função anônima que adiciona seus argumentos e adiciona 3. (op - @1 3) é uma função anônima que subtrai 3 de seu argumento. A sintaxe @1 denota a inserção do primeiro argumento de funções na posição determinada na expressão. (op mapcar append) é uma função para a qual podemos passar várias listas, cada uma contendo listas. A função pegará essas listas na tupla e as anexará juntas. Esta é a base para a lógica semelhante à pasta para unir os dados.

A macro opip usa um monte de expressões e insere essencialmente op nelas e, em seguida, cria uma função que canaliza os dados através das funções anônimas resultantes. Isso é uma simplificação, mas vai fazer.

(partition* @1 (op where (op equal ""))) divide a lista de linhas brutas do arquivo em partições com base no corte da lista em que seus elementos são linhas em branco ( equal para a sequência vazia) e na remoção dessas entradas. (A função partition sem o * em seu nome deixará esses espaços em branco).

(tuples 3) reúne estas partições em grupos de 3.

Estes grupos de 3, ou tripletos, devem ser acumulados em paralelo: os primeiros elementos dos trios devem ser anexados em uma única lista, os segundos elementos em uma única lista e assim por diante. Esse é o trabalho de (reduce-left (op mapcar append)) . A função do kernel (op mapcar append) recebe um par de trios e catena suas entradas correspondentes para criar um trio de mesclagem. A função reduce-left dizima a lista de trigêmeos até um único trio.

Este trio mestre é então aplicado como argumentos a uma chamada mapdo , na expressão final (apply mapdo (op pprinl ...)) . mapdo recebe uma função como seu argumento mais à esquerda, gerado por (op ...) mais uma vez. Os argumentos restantes são os três elementos do trio gigante, representando as três colunas de dados. As colunas são mapeadas linha por linha através da função anônima.

A função anônima usa três argumentos que são referenciados na string quasiliteral '@{1 6} @{2 6} @{3 6}' , onde @{1 6} significa @1 , definido em uma largura de campo de 6. Esse quasiliteral de cadeia que interpola os três argumentos (três elementos extraídos em pares). por mapdo do trio de colunas) constrói uma string que a função anônima passa para pprinl , que imprime com uma nova linha.

    
por 10.12.2015 / 00:33