Wie kann man Strings mit Zahlen sortieren?

37

Wenn ich diese Dateien in einem Verzeichnis habe

cwcch10.pdf
cwcch11.pdf
cwcch12.pdf
cwcch13.pdf
cwcch14.pdf
cwcch15.pdf
cwcch16.pdf
cwcch17.pdf
cwcch18.pdf
cwcch1.pdf
cwcch2.pdf
cwcch3.pdf
cwcch4.pdf
cwcch5.pdf
cwcch6.pdf
cwcch7.pdf
cwcch8.pdf
cwcch9.pdf

Wie kann ich sie in Bash auflisten, damit sie in aufsteigender numerischer Reihenfolge basierend auf dem Zahlenteil der Zeichenfolge sind? So ist die resultierende Reihenfolge cwcch1.pdf, cwcch2.pdf, ..., cwcch9.pdf, cwcch10.pdfusw.

Letztendlich versuche ich, die PDFs pdftkmit so etwas wie dem Folgenden zu verknüpfen

pdftk `ls *.pdf | sort -n` cat output output.pdf

Das funktioniert aber nicht, da meine Sortierung falsch ist.

ngm
quelle
Vielen Dank für all die tollen Antworten darauf. Wie immer bei Unix gibt es viele verschiedene hervorragende Möglichkeiten, diese Katze zu häuten.
ngm

Antworten:

7

So etwas könnte tun, was Sie wollen, obwohl es einen etwas anderen Ansatz hat:

pdftk $(for n in {1..18}; do echo cwcch$n.pdf; done) cat output output.pdf
retracile
quelle
Aha, nette Annäherung! Es macht ja was ich was, danke.
ngm
62

Sie sortkann die Fähigkeit hat , dies zu tun für Sie:

sort --version-sort
Bis auf weiteres angehalten.
quelle
Auszug aus dem relevanten Eintrag in der -V, --version-sort natural sort of (version) numbers within text
Sortiermanpage
Das ist was du brauchst. Aber wenn Ihre Sortierung diese Option nicht bietet, schauen Sie sich diesen Beitrag an: stackoverflow.com/a/4495368/1240018
eventhorizon
30

Für dieses Beispiel können Sie auch Folgendes tun:

ls *.pdf | sort -k2 -th -n

Das heißt, Sie sortieren numerisch (-n) nach dem zweiten Feld (-k2), wobei Sie 'h' als Feldtrennzeichen (-th) verwenden.

larsks
quelle
Teilen und dann sortieren auf einem Feld - das ist ein großartiger Tipp, den ich Ihnen in Zukunft sicherlich empfehlen werde, danke.
ngm
6

Sie können die -vOption in GNU verwenden ls: natürliche Art von (Versions-) Zahlen innerhalb von Text.

ls -1v cwcch*

Dies funktioniert nicht mit BSD ls(zB unter OS X), wo die -vOption eine andere Bedeutung hat.

Ashutosh Vishwa Bandhu
quelle
Dies ist die einfachste Lösung, es braucht mehr positive Stimmen!
davidparks21
2

Verwenden Sie die Shell-Erweiterung direkt in einer Befehlszeile. Die Erweiterung sollte sie richtig bestellen. Wenn ich die pdftkBefehlszeilensyntax richtig verstehe , wird dies tun, was Sie wollen:

# shell expansion with square brackets
pdftk cwcch[1-9].pdf cwcch1[0-9].pdf cat output output.pdf

# shell expansion with curly braces
pdftk cwcch{{1..9},{10..18}}.pdf cat output output.pdf

Oder Sie können einen anderen Ansatz versuchen. Wenn ich so etwas tun muss, versuche ich normalerweise, meine Zahlen im Voraus richtig zu formatieren. Wenn ich zu spät dran bin und die PDFs bereits wie in Ihrem Beispiel nummeriert sind, benutze ich Folgendes, um sie neu zu nummerieren:

# rename is rename.pl aka prename -- perl rename script
# this adds a leading zero to single-digit numbers
rename 's/(\d)/0$1/' cwcch[1-9].pdf

Jetzt lsfunktioniert die Standardsortierung ordnungsgemäß.

Quacksalber
quelle
2
Vielleicht etwas prägnanter:pdftk cwcch{{1..9},{10..18}}.pdf ...
Bis auf weiteres angehalten.
guter Tipp, hinzugefügt in. Ist das eine Standard-Bourne-Shell-Erweiterungssyntax oder eine bashErweiterung?
Quacksalber 6.
2

Hier ist eine Methode, die nur sort verwendet:

ls | sort -k1.6n
Schotte
quelle
0

Sortieren -g wird verwendet, um die Nummern in aufsteigender Reihenfolge zu sortieren.

anthony@mtt3:~$ sort --help | egrep "\-g"
-g, --general-numeric-sort  compare according to general numerical value


Die folgende Zeile durchläuft eine Datei mit den Namen der PDF-Dateien und fasst die Zahlen nur mit egrep -o zusammen und sortiert die Zahlen mit sort -g in aufsteigender Reihenfolge . Dann füttert es sed mit diesen Zahlen und steckt sie ein. Dann löscht es die Ausgabe von Duplikaten mit uniq.


Anstelle von uniq können Sie auch awk verwenden:

awk '!x[$0]++'

Das obige ist äquivalent zu uniq.


Was Sie suchen, ist dieser eine Liner:

for i in `cat tmp | egrep -o "[0-9]*" | sort -g`; do cat tmp | sed "s/\(^[a-z]*\)\([0-9]*\)\(\.pdf\)/\1$i\3/g" | uniq; done


Inhalt von tmp:

anthony@mtt3:~$ cat tmp
cwcch10.pdf
cwcch11.pdf
cwcch12.pdf
cwcch13.pdf
cwcch14.pdf
cwcch15.pdf
cwcch16.pdf
cwcch17.pdf
cwcch18.pdf
cwcch1.pdf
cwcch2.pdf
cwcch3.pdf
cwcch4.pdf
cwcch5.pdf
cwcch6.pdf
cwcch7.pdf
cwcch8.pdf
cwcch9.pdf 

BEARBEITEN:

Ausgabe des Befehls:

anthony@mtt3:~$ for i in `cat tmp | egrep -o "[0-9]*" | sort -g`; do cat tmp | sed "s/\(^[a-z]*\)\([0-9]*\)\(\.pdf\)/\1$i\3/g" | uniq; done

cwcch1.pdf
cwcch2.pdf
cwcch3.pdf
cwcch4.pdf
cwcch5.pdf
cwcch6.pdf
cwcch7.pdf
cwcch8.pdf
cwcch9.pdf
cwcch10.pdf
cwcch11.pdf
cwcch12.pdf
cwcch13.pdf
cwcch14.pdf
cwcch15.pdf
cwcch16.pdf
cwcch17.pdf
cwcch18.pdf
Aguevara
quelle
Funktioniert dieser eine Liner mit der tmpDatei? Irgendeine Ausgabe zum Einfügen in die Antwort?
Xen2050,
Ja. Ich habe die Ausgabe in mein OP im Abschnitt Bearbeiten aufgenommen.
Aguevara