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.


Merci pour toutes les bonnes réponses à cela. Comme toujours avec Unix, il existe de nombreux excellents moyens de peauner ce chat.
ngm

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

Aha, belle approche! Il fait en effet ce que je fais, merci.
ngm


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).


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.


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.


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

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

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.