Classificação de blocos de um arquivo no unix [closed]

1

Eu tenho arquivo como.

HR|testing file
BH|100
B2|cat|10
B2|dog|20
BT|4
BH|105
B2|apple|10
B2|banana|20
B2|melon|10
BT|5
BH|102
B2|fan|10
B2|bulb|20
B2|washer|10
B2|dryer|10
BT|6
TR|17

Eu preciso classificar os blocos com base no segundo campo no registro BH de cada bloco. As linhas nos blocos devem permanecer intactas. Para o arquivo acima, a saída esperada é:

HR|testing file
**BH|100**
B2|cat|10
B2|dog|20
BT|4
**BH|102**
B2|fan|10
B2|bulb|20
B2|washer|10
B2|dryer|10
BT|6
**BH|105**
B2|apple|10
B2|banana|20
B2|melon|10
BT|5
TR|17
    
por Rkt 24.04.2018 / 20:05

2 respostas

2

Isso deve funcionar e classificar cada bloco com base em # em BH|# como linha de cabeçalho de bloco e em% ascendenteBH|100, BH|102 , BH|105 , ... order.

awk -v RS='BH|TR' 'NR>1{ seen[NR]=$0; next } { printf $0 }
   END{ TR="TR"seen[NR]; delete seen[NR]; asort(seen);  
        for(x in seen) printf "BH"seen[x]; printf TR }' infile

HR|testing file
BH|100
B2|cat|10
B2|dog|20
BT|4
BH|102
B2|fan|10
B2|bulb|20
B2|washer|10
B2|dryer|10
BT|6
BH|105
B2|apple|10
B2|banana|20
B2|melon|10
BT|5
TR|17
  • Este RS='BH|TR' define os BH e TR como separadores de registros (o padrão é \n ewline).

  • Este bloco NR>1{ seen[NR]=$0; next } será executado para todos os ecords R , mas primeiro ( NR é N umber de R ecord ); assim, para cada Número de Registro como a chave (Índice) de um array associado chamado visto , o valor de todo o registro será definido para ele e depois ler next record.

  • Se não for o primeiro registro, então { printf $0 } . Isso será executado apenas uma vez, porque da próxima vez NR>1 .

No final, o bloco END{ ... } será executado e será executado:

  • Este TR="TR"seen[NR] copiando o último registro da matriz inserida em uma variável chamada TR e, em seguida, excluí-lo da matriz delete seen[NR] .
  • Esse asort(seen) classifica a matriz vista com base em seus valores salvos; então
  • Fazemos o loop de for(x in seen) sobre essa matriz e printf "BH"seen[x]
  • No final, imprimimos o TR .

Se você não se importa com a primeira e a última linha do seu arquivo, você também pode:

sed '1d; $d' infile |awk '{printf $0(/^BT/?"\n":"#")}' |sort |tr '#' '\n'
    
por 25.04.2018 / 11:10
-2

Eu encontrei uma maneira rápida e fácil de fazer isso. Por favor, sugira se existe uma maneira melhor de fazê-lo.

Removidos os registros de cabeçalho e trailer. Combinado e colocado em um # como um separador de linha entre as linhas em um bloco em uma linha. Ordenado por campo específico Substituiu o # por nova linha

gawk '/^HC/ && line {print line; line=""} {line = line ? line"#"$0 : $0} END {print line}' input.txt | sort -t"|" -nk 13 | tr '#' '\n' > finaloutput.txt
    
por 25.04.2018 / 03:45

Tags