Ordene a saída do script, mas mantenha as linhas juntas

1

Eu quero ler alguns arquivos e classificar a saída.

Por exemplo:

cat example.conf  
Order: 0   
Package: example 

cat another.conf  
Order: 2  
Package: another

cat file.conf  
Order: 1  
Package: file

Eu produzi-os com: awk '/Order|Package/' conf/*.conf :

Order: 2  
Package: another  
Order: 0  
Package: example  
Order: 1  
Package: file

Eu gostaria que a saída fosse classificada pelo número após Order: , mas sem quebrar a relação entre as linhas, como:

Order: 0  
Package: example  
Order: 1  
Package: file  
Order: 2  
Package: another
    
por PaulNaga 15.07.2017 / 14:15

5 respostas

4

Se você tem o GNU awk > 4.0, e assumindo que o registro Order sempre precede o registro Package , então

gawk '/^Order/ {order = $2} /^Package/ {p[order] = $0} 
  END {
    PROCINFO["sorted_in"] = "@ind_num_asc"
    for (i in p) {print "Order:", i; print p[i]}
  }
' conf/*.conf
Order: 0
Package: example
Order: 1
Package: file
Order: 2
Package: another

Para os antigos gawk , você pode usar asorti :

gawk '/^Order/ {order = $2} /^Package/ {p[order] = $0} 
  END {
    n = asorti(p,b)
    for (i=1;i<=n;i++) {print "Order:", i; print p[b[i]]}
  }
' conf/*.conf
    
por 15.07.2017 / 14:39
0

Funciona para arquivos, que contém apenas duas linhas.

sed -n 'N; s/\n//p' *.conf | sort | sed -n 's/\(Package\)/\n/p'

Explicação:

  1. sed -n 'N; s/\n//p' *.conf - remove a nova linha entre duas linhas, ou seja, une duas linhas contíguas na linha.
  2. sort - classifica linhas longas, o que foi feito na etapa anterior.
  3. sed -n 's/\(Package\)/\n/p' - retorna a nova linha ao seu lugar.

Saída:

Order: 0   
Package: example 
Order: 1  
Package: file
Order: 2  
Package: another
    
por 15.07.2017 / 16:25
0

Uma abordagem Unix ingênua:

awk '/Order|Package/' conf/*.conf |           # get your usual output
    paste - - |                               # convert two lines to one
        sort -n -k2,2 |                       # sort numerically
            awk '{print $1,$2;print $3,$4}'   # re-print in two columns
    
por 16.07.2017 / 04:19
0

Script em Python

#!/usr/bin/env python
from __future__ import print_function
import sys

def get_order_package(filename):
    order=None
    package=None
    with open(filename) as f:
        for line in f:
            if line.startswith('Order:'):
                order=int(line.strip().split()[1])
            if line.startswith('Package:'):
                package=line.strip().replace("Package: ",'')
    return (order,package)

order_list=[]
for argument in sys.argv[1:]:
    order_list.append(get_order_package(argument))
order_list.sort(key=lambda x: x[0])

for i in order_list:
    print('Order:',i[0])
    print('Package:',i[1])

Este script define a função get_order_package() que analisa o arquivo e retorna a tupla no formato (integer,package_string) . Passamos todos os arquivos como argumentos da linha de comando e fazemos iterações sobre eles, executando a função explicada acima para cada um. Isso cria uma lista, nós a classificamos e iteramos novamente, imprimindo cada parte da tupla da nova lista classificada.

Execução de teste

$ cat example_1.conf                                               
Order: 0   
Package: example_1

$ cat example_2.conf                                               
Order: 2
Package: example_2

$ cat example_3.conf                                               
Order: 1
Package: example_3

$ ./parse_conf.py  *.conf                                          
Order: 0
Package: example_1
Order: 1
Package: example_3
Order: 2
Package: example_2
    
por 16.07.2017 / 04:49
0

Isso também funciona:

grep -e ^Order -e ^Package 'grep ^Order *.conf | awk -F: '{printf("%s:%s\n",$NF,$0);}' |sort| awk -F: '{print $2}''

Explicação (abaixo do formato multi-line é apenas para demonstração, ele não funciona no bash porque o comando de linha única resultante não pode lidar com comentários ):

$ grep -e ^Order -e ^Package ' \                # grep for lines starting with "Order" or "Package"; start nested command 
> grep ^Order *.conf | \                        # grep for lines starting with "Order" in files *.conf
> awk -F: '{printf("%s:%s\n",$NF,$0);}' | \     # prefixing order number with a separating colon
> sort | \                                      # sort by order number
> awk -F: '{print $2}' \                        # extract file name alone ; now filenames are ordered by the order number contained within them
> '                                             # end nested command
    
por 17.07.2017 / 19:13