Como analisar um arquivo de texto delimitado por espaço

1

Eu tenho um arquivo de texto como este:

Fam1000: CMIN|CMIN_9-RA CMIN|ABC_7-RA GCLA|EFX5.1 GCUC|GCUC_7-RA
Fam1001: GCLA|EFX6.1 GCLA|EFX7.1
Fam1002: GCLA|EFX5.1 GCLA|EFX2.1 GCUC|GCUC_8-RA GCUC|GCUC_8-RA
Fam1003: CMIN|CMIN_001265-RA CMIN|CMIN_007282-RA

Neste arquivo, cada linha contém um número de valores (separados por espaços). Cada valor tem um identificador de grupo específico para seu grupo que precede o símbolo de pipe (por exemplo, CMIN | CMIN_9-RA e CMIN | ABC_7-RA pertencem ao grupo CMIN). As letras que seguem o pipe podem estar em letras e números aleatórios.

Conhecendo o número total e o nome dos identificadores de grupo no arquivo (neste caso, eu tenho 3: que são CMIN, GCLA e GCUC). Agora quero analisar esse arquivo em um arquivo que mostra o número de valor de cada grupo para cada linha. No final, gostaria de ter a saída assim (que pode ser separada por espaço ou por tabulação):

            CMIN    GCLA    GCUC
Fam1000:    2       1       1
Fam1001:    0       2       0
Fam1002:    0       2       2
Fam1003:    2       0       0

Eu estava pensando em excluir primeiro todos os elementos depois da | para cada um dos valores, conte o número de identificadores exclusivos para cada linha, mas não consegui descobrir como fazer isso com o awk. Alguém pode ajudar por favor?

Além disso, este é apenas um exemplo simplificado, o arquivo real é bastante grande, com alguns milhares de linhas e algumas dezenas de grupos.

Obrigado.

    
por atd 24.04.2015 / 11:07

1 resposta

2

Não é a solução mais bonita, mas funciona. Este script foi testado no Linux Ubuntu. Pode não funcionar em um Mac porque eu uso gawk .

Você precisa salvar o seguinte código em um arquivo, por exemplo, parsetext.sh

Execute este comando para ativar a execução:

chmod +x parsetext.sh

Em seguida, execute-o com o seu inputfile.txt:

./parsetext.sh inputfile.txt

A seguir, o script que faz o trabalho:

#!/bin/bash
sed -e 's/|[^ ]\+//g; s/://' "$1"|\
gawk '{

        for ( i = 2; i <= NF; i++) {
        rows[$1][$i]++
        keys[$i]++
    } 
    } 
END {
    n = asorti(keys, tmp)
    printf("\t")
    for ( i=1; i<= n; i++) { printf("%s\t", tmp[i]) }
    printf("\n")
    for ( r in rows ) { 
        printf("%s\t", r)
        for (i=1; i<= n; i++) {
            value = 0
            k = tmp[i]
            if (rows[r][k] > 0) value = rows[r][k] 
            printf("%s\t", value)
        }
        printf("\n")
    }

}'

Exemplo de saída:

    CMIN    GCLA    GCUC    
Fam1000 2   1   1   
Fam1001 0   2   0   
Fam1002 0   2   2   
Fam1003 2   0   0   
    
por 24.04.2015 / 18:36