web-dev-qa-db-fra.com

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

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 pour 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 de concaténer le fichier .pdf avec pdftk avec quelque chose comme:

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

mais cela ne fonctionne pas car mon tri est faux.

36
ngm

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
7
retracile

Votre sort pourra peut-être le faire pour vous:

sort --version-sort
58
Dennis Williamson

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

30
larsks

Vous pouvez utiliser l'option -v dans GNU ls: sorte naturelle de numéros (de version) dans le texte.

ls -1v cwcch*

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

6

Utilisez l'extension Shell directement dans une ligne de commande. L'expansion devrait les commander correctement. Si je comprends bien la syntaxe de la ligne de commande de pdftk, 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 tri standard ls fonctionnera correctement.

2
quack quixote

Voici une méthode utilisant simplement le tri:

ls | sort -k1.6n
2
Scot

Trier -g est utilisé pour trier les nombres dans l'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 numéros uniquement avec egrep -o et utilise trier -g trier les nombres en ordre croissant. Ensuite, il envoie ces nombres à sed et les branche. Puis supprime la sortie des doublons avec uniq.


À la place de uniq, vous pouvez également utiliser awk:

awk '!x[$0]++'

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


Ce que tu recherches, c'est ce bon mot:

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
0
Aguevara