2012-07-03 14 views
7

Sto cercando di ordinare un elenco di nomi seguiti da un'altra stringa come ad esempio:Come ordinare con più righe in bash?

John Doe 
AVAIL 

Sara Doe 
CALL 

Jim Doe 
AVAIL 

che sto cercando di risolvere questi per nome, ma non riesco a capirlo con specie. Qualcuno può fornire una guida?

mio risultato finale sarebbe simile a questa:

Jim Doe 
AVAIL 

John Doe 
AVAIL 

Sara Doe 
CALL 

molto apprezzato!

+0

È interessante notare che, dal vostro esempio, la sua non è chiaro se si ordina per quanto riguarda la prima o la seconda linea;) –

+0

dispiace vorrei davvero piacerebbe ordina per ordine alfabetico per la prima linea. –

risposta

6

Probabilmente lungi dall'essere ottimale, ma

sed -r ':r;/(^|\n)$/!{$!{N;br}};s/\n/\v/g' names | sort | sed 's/\v/\n/g' 

sembra fare il lavoro (names è il file con i record). Ciò consente record di lunghezza arbitraria, non solo di 2 righe.

+0

Ha sicuramente funzionato per il mio scopo. –

+1

@lev per coloro che non sono abbastanza "fluenti" in "sed", potresti fornire una breve narrazione della prima parte dell'espressione? Il tuo approccio di base è quello di eliminare i newline (mettendo '\ v'? Al suo posto), ordinando una lunga riga, e quindi sostituendo' \ v' per '\ n'? – Levon

+0

@Levon Hai perfettamente ragione :) Legge tutto fino a una riga vuota (un record), quindi modifica le nuove righe in "\ v'. Ora tutti i record sono su singole righe. Sono ordinati, quindi '\ v' viene riconvertito in' \ n'. –

0

Non so se funzionerà per te ma con alcune limitazioni qui c'è una linea che fa quello che ti serve.

awk '{if ((NR%2-1)==0) {line=sprintf("%-30s",$0)} else {print line ":" $0}}' | \ 
    sort --key=1,30 | tr ':' '\n' 

Ipotesi: ci sono righe vuote tra i record, il nome è sempre inferiore a 30 caratteri e non c'è : utilizzato nel testo.

Sono sicuro che è possibile capire come modificarlo se le ipotesi sono diverse.

In poche parole, unisce due linee utilizzando ':' come separatore, esegue il pad della prima riga a 30 caratteri e ordina utilizzando i primi 30 caratteri. Quindi interrompe le linee.

0

non direttamente, ma è possibile utilizzare alcune forme intermedie come questa. presumo che il tuo valore (CALL, AVAIL, ecc.) sia limitato. altrimenti è necessario utilizzare schemi più complicati, ma è possibile farlo. in realtà tutto può essere fatto in bash :-)

cat sorting | sed -n '1h; 1!H; ${ g; s/\nCALL\n/::CALL::/g; s/\nAVAIL\n/::AVAIL::/g ; s/\nAVAIL/::AVAIL::/g p }' | sort | sed "s/::/\n/g" 
Jim Doe 
AVAIL 

John Doe 
AVAIL 

Sara Doe 
CALL 
Problemi correlati