Precisa que o Awk ou o Unix Script transponha / gire no seguinte padrão

1

O arquivo contém dados no seguinte formato (a primeira linha é o cabeçalho):

N ; A ; B 
=========
1 ; 01;02 
2; 02;02 

Com base na primeira coluna, espero que a seguinte saída: N coluna permanece o mesmo, no entanto, os outros podem crescer, pode ser C, D, E etc e os valores correspondentes podem ser capturados.

1;A;01 
2;A;02
1:B;02
2;B;02 

Como posso fazer isso?

    
por kenyjohn 19.06.2017 / 18:37

3 respostas

0

Aqui está um trecho de código usando o Python ...

Código:

# read in the data
with open('data_file', 'rU') as f:
    # read in the header
    header = [x.strip() for x in f.readline().split(';')]

    # drop the ======
    dump_marker = f.readline()

    # get the rest of the data
    data = [[x.strip() for x in line.split(';')] for line in f.readlines()]

# print the data in new format
for i, col in enumerate(header[1:]):
    for line in data:
        print("{};{};{}".format(line[0], col, line[i+1]))

data_file:

N ; A ; B
=========
1 ; 01;02
2 ; 02;02

Resultado:

1;A;01
2;A;02
1;B;02
2;B;02
    
por 19.06.2017 / 18:54
0

No bash, isso pode ser feito com comandos internos, tail e cut :

#! /bin/bash
# Get header line
header=$( head -n 1 data_file )
# Make a variable with all delimiters (2)
delimiters=${header//[^;]/}
# Make an array with all column names
declare -a colnames=( ${header//;/ } )
# For all columns one at the time...
for C in $(seq 2 $((${#delimiters}+1)) ) ; do
    index=$((C-1))
    # Skip first 3 lines of data_file
    tail --lines=+3 data_file | cut -d\; -f1,$C | while read; do
        # Replace first ';' with column name
        line=${REPLY/;/;${colnames[$index]};}
        # Remove all spaces and print
        echo ${line// /}
    done
done

Explicação:

Obtenha a primeira linha do arquivo em uma variável (que pode ser modificada)

header=$( head -n 1 data_file )

Remova todos os caracteres da variável espere o delimitador cemi-cólon

delimiters=${header//[^;]/}

Agora, a variável $ delimiters contém ';;'

Substitua todos os ';' com espaços. Vai dar "N A B". Um ou mais espaços é o delimitador da matriz:

declare -a colnames=( ${header//;/ } )

Obtenha o número de caracteres em uma variável:

${#delimiters}

Adicione um:

$((${#delimiters}+1))

Então

$(seq 2 $((${#delimiters}+1)) )

é igual a:

$(seq 2 3 )

O índice na variável vai de 0..n, depois -1 para procurar nomes de coluna:

index=$((C-1))

Leia o arquivo, pule as 3 primeiras linhas, mostre apenas o número da coluna $C , leia a linha na variável $REPLY :

tail --lines=+3 data_file | cut -d\; -f1,$C | while read; do
    
por 19.06.2017 / 19:35
0

E uma solução usando awk :

awk -F';' '{ gsub(/ /,"");}
           NR==1 { cols = split($0, col); }
           NR > 2 { for (i = 2; i <= cols; i++) {
                        data[col[i]";"$1] = $1";"col[i]";"$i; }
                  }
           END { no = asorti(data, sorted);
                 for (i = 1; i <= no; i++) {
                     print data[sorted[i]]; }
               }' input
    
por 20.06.2017 / 11:23