En bash, comment trier les chaînes contenant des nombres?

37

Si j'ai ces fichiers dans un répertoire

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

comment puis-je les lister dans Bash afin qu'ils soient dans l'ordre numérique croissant basé sur la partie numérique de la chaîne. Donc, l'ordre résultant est cwcch1.pdf, cwcch2.pdf, ..., cwcch9.pdf, cwcch10.pdf, etc.

Ce que j’essaie de faire, c’est concaténer les fichiers PDF pdftkavec quelque chose comme ce qui suit:

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

mais cela ne fonctionne pas car mon tri est faux.

ngm
la source
Merci pour toutes les bonnes réponses à cela. Comme toujours avec Unix, il existe de nombreux excellents moyens de peauner ce chat.
ngm
stackoverflow.com/questions/13088370/sort-numerically
Ciro Santilli a annoncé le 10/05

Réponses:

7

Quelque chose comme cela pourrait faire ce que vous voulez, bien que l'approche soit légèrement différente:

pdftk $(for n in {1..18}; do echo cwcch$n.pdf; done) cat output output.pdf
rétracile
la source
Aha, belle approche! Il fait en effet ce que je fais, merci.
ngm
62

Vous sortpouvez avoir la capacité de le faire pour vous:

sort --version-sort
En pause jusqu'à nouvel ordre.
la source
Extrait de l'entrée pertinente dans la page du manuel de tri: -V, --version-sort natural sort of (version) numbers within text
panmari le
C'est ce dont tu as besoin. Mais si votre tri ne fournit pas cette option, jetez un coup d'œil à cet article: stackoverflow.com/a/4495368/1240018
eventhorizon
30

Pour cet exemple particulier, vous pouvez également le faire:

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

En d’autres termes, triez numériquement (-n) sur le deuxième champ (-k2) en utilisant «h» comme séparateur de champ (-th).

alsacs
la source
Fractionner puis trier sur un champ - c'est un bon conseil qui, je suis sûr, sera utile à l'avenir, merci.
ngm
6

Vous pouvez utiliser l' -voption dans GNU ls: sorte naturelle de nombres (version) dans le texte.

ls -1v cwcch*

Cela ne fonctionne pas avec BSD ls(par exemple sous OS X), où l' -voption a une signification différente.

Ashutosh Vishwa Bandhu
la source
C'est la solution la plus simple, il a besoin de plus de votes positifs!
davidparks21
2

Utilisez l'expansion du shell directement dans une ligne de commande. L'expansion devrait les commander correctement. Si je comprends pdftkbien la syntaxe de ligne de commande, cela fera ce que vous voulez:

# 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

Ou vous pouvez essayer une approche différente. Lorsque j'ai besoin de faire quelque chose comme ça, j'essaie généralement de mettre mes chiffres en forme correctement à l'avance. Si j'arrive tard et que les fichiers PDF sont déjà numérotés comme dans votre exemple, je vais utiliser ceci pour renuméroter:

# 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

Maintenant, le lstri standard fonctionnera correctement.

Quack Quack
la source
2
Peut-être un peu plus succinctement:pdftk cwcch{{1..9},{10..18}}.pdf ...
pause jusqu'à nouvel avis.
bon conseil, ajouté. Est-ce une syntaxe standard d’extension du shell Bourne ou une bashextension?
Quack Quichotte
2

Voici une méthode utilisant simplement le tri:

ls | sort -k1.6n
Écossais
la source
0

Sort -g est utilisé pour trier les nombres par ordre croissant.

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


Le liner suivant parcourt un fichier avec les noms des fichiers PDF et saisit les nombres uniquement avec egrep -o et utilise sort -g pour trier les nombres par ordre croissant . Ensuite, il envoie ces nombres à sed et les branche. Puis supprime la sortie des doublons avec uniq.


Au lieu de uniq, vous pouvez également utiliser awk:

awk '!x[$0]++'

Ce qui précède est équivalent à uniq.


Ce que vous cherchez, c'est ce 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


Contenu de 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 

MODIFIER:

Sortie de commande:

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
la source
Est- ce que cette doublure fonctionne sur le tmpfichier? Une sortie à coller dans la réponse?
Xen2050
Oui. J'ai inclus la sortie dans mon OP sous la section d'édition.
Aguevara