Come ordinare questo output 1,10,11..2

Aug 24 2020

A volte ho bisogno di aggiungere più disco a un database; per questo, ho bisogno di elencare i dischi per vedere quali dischi esistono già.

Il problema è che l'output è sempre ordinato come 1,10,11,12 ... 2,20,21 ... 3 ecc.

Come posso ordinare questo output nel modo desiderato? Un semplice sortnon funziona; Ho anche provato a usare sort -t.. -k.. -n.

Esempio di ciò che devo ordinare:

[root@server1 ~]# oracleasm listdisks
DATA1
DATA10
DATA11
DATA12
DATA2
DATA3
DATA4
DATA5
DATA6
DATA7
DATA8
DATA9
FRA1
FRA10
FRA11
FRA2
FRA3
..
OCR1
OCR2
OCR3
....

Come vorrei vedere l'output:

DATA1
DATA2
DATA3
DATA4
DATA5
DATA6
DATA7
DATA8
DATA9
DATA10
DATA11
DATA12
FRA1
FRA2
FRA3
..
..
FRA10
FRA11
..
OCR1
OCR2
OCR3
....

Risposte

31 iruvar Aug 24 2020 at 06:03

La soluzione migliore è passare a GNU sort, con sortl' --version-sortopzione GNU abilitata

così sarebbe oracleasm listdisks | sort --version-sort

Dalla pagina delle informazioni

--version-sort’
     Sort by version name and number.  It behaves like a standard sort,
     except that each sequence of decimal digits is treated numerically
     as an index/version number.  (*Note Details about version sort::.)

Sul tuo input mi dà

DATA1
DATA2
DATA3
DATA4
DATA5
DATA6
DATA7
DATA8
DATA9
DATA10
DATA11
DATA12
FRA1
FRA2
FRA3
FRA10
FRA11
OCR1
OCR2
OCR3
10 TimurShtatland Aug 25 2020 at 01:54

Se sort --version-sortnon è disponibile, dividere in 2 campi: campo 1 = non cifre iniziali e campo 2 = numero intero e stampare i campi con TAB tra di loro. Quindi utilizzare sortsu 2 campi delimitati da TAB, quindi rimuovere il TAB. Collegare tramite tubi per evitare overhead di I / O. Ecco un esempio con una fetta minima dei dati dall'OP, più alcuni record aggiuntivi:

echo 1 10 2 11 DATA DATA1 DATA10 DATA11 DATA2 FRA FRA1 FRA10 FRA11 FRA2 | \
    xargs -n1 | \
    perl -lne 'print join "\t", /(\D*)(\d*)/' | \
    sort -k1,1 -k2,2n | \
    perl -pe 's/\t//'

Stampe:

1
10
11
2
DATA
DATA1
DATA2
DATA10
DATA11
FRA
FRA1
FRA2
FRA10
FRA11

DETTAGLI:

Gli one-liner di perl usano questi flag della riga di comando
-e:: dice a Perl di cercare il codice in-line, invece che in un file.
-n: scorre sull'input una riga alla volta, assegnandola per $_impostazione predefinita.
-l: elimina il separatore di riga di input ( "\n"su * NIX per impostazione predefinita) prima di eseguire il codice in linea e aggiungilo durante la stampa.
-p: uguale a -n, ma anche printla riga alla fine di ogni ciclo (elimina esplicito print).

All'interno della prima riga, \dè presente qualsiasi cifra (0-9) e \Dqualsiasi non cifra. Ciascuno di questi modelli viene ripetuto 0 o più volte (utilizzando *). I due modelli vengono catturati utilizzando le parentesi e restituiti come un LISTdi due campi, che vengono uniti su una TAB e stampati.

Il secondo one-liner Perl rimuove semplicemente il primo TAB viene trovato senza nulla (stringa vuota) e stampa la riga.

Per sortsu 2 campi, vengono utilizzate queste opzioni -k1,1:: ordina sul campo 1 ASCIIbeticamente. Quindi::
-k2,2nse il campo 1 è lo stesso, ordinare il campo 2 numericamente ( -nopzione).
Notare che il numero del campo viene ripetuto due volte (ad es. 1,1), Per impedire l'ordinamento sul resto della riga e limitare l'ordinamento solo a questo numero di colonna.