Як сказати в bash, як сортувати рядки з числами в них?


37

Якщо я маю ці файли в каталозі

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

як я можу перерахувати їх у Bash, щоб вони були у порядку зростання чисельних даних, виходячи з числової частини рядка. Тож отримане замовлення є cwcch1.pdf, cwcch2.pdf, ..., cwcch9.pdf, cwcch10.pdfі т.д.

Що я намагаюся зробити в кінцевому рахунку - це об'єднати файли pdfs pdftkз чимось подібним

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

але це не працює, оскільки моє сортування неправильне.


Дякую за всі чудові відповіді на це. Як завжди з Unix, існує багато різних відмінних способів, як шкіру цього кота.
ngm

Відповіді:


7

Щось подібне може робити те, що ви хочете, хоча це дещо інший підхід:

pdftk $(for n in {1..18}; do echo cwcch$n.pdf; done) cat output output.pdf

Ага, приємний підхід! Це дійсно робить те, що я, дякую.
ngm

62

Ви sortможете це зробити для вас:

sort --version-sort

Витяг із відповідного запису на сторінці сортування людини: -V, --version-sort natural sort of (version) numbers within text
panmari

Це те, що вам потрібно. Але якщо Ваш вигляд не поставляє цей варіант , подивіться на цей пост: stackoverflow.com/a/4495368/1240018
eventhorizon

30

Для цього конкретного прикладу ви також можете зробити це:

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

Тобто сортуйте числово (-n) у другому полі (-k2), використовуючи 'h' як роздільник поля (-й).


Розбиття та сортування на одному полі - це чудова порада, яка, я впевнений, буде корисною в майбутньому, дякую.
ngm

6

Ви можете використовувати -vопцію в GNU ls: натуральний сорт (версія) чисел у тексті.

ls -1v cwcch*

Це не працює з BSD ls(наприклад, на OS X), де -vпараметр має інше значення.


Це найпростіше рішення, воно потребує більшої кількості людей!
davidparks21

2

Використовуйте розширення оболонки безпосередньо в командному рядку. Розширення має впорядкувати їх належним чином. Якщо я pdftkправильно розумію синтаксис командного рядка, це зробить те, що ви хочете:

# 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

Або ви можете спробувати інший підхід. Коли мені потрібно зробити щось подібне, я зазвичай намагаюся достроково форматувати свої номери. Якщо я заходжу в нього пізно, а PDF-файли вже пронумеровані, як ваш приклад, я використаю це для перенумерації:

# 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

Тепер стандартне lsсортування буде працювати належним чином.


2
Можливо, трохи більш лаконічно:pdftk cwcch{{1..9},{10..18}}.pdf ...
Призупинено до подальшого повідомлення.

Хороший підказок, доданий в. Це стандартний синтаксис розширення оболонки Bourne або bashрозширення?
шарлатаний кіхот


0

Сортувати -g використовується для сортування чисел у порядку зростання.

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


Наступний один вкладиш перебирає файл з іменами PDF-файлів і захоплює номери лише egrep -o і використовує сортування -g для сортування чисел у порядку зростання . Потім він подає ці числа на sed і підключає їх. Потім виводить висновки дублікатів з uniq.


Замість uniq ви можете також використовувати awk:

awk '!x[$0]++'

Викладене вище рівнозначно uniq.


Що ви шукаєте, це один вкладиш:

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


Зміст 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 

Редагувати:

Виведення команди:

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

Чи працює цей один вкладиш на tmpфайл? Будь-який вихід, який потрібно вставити у відповідь?
Xen2050

Так. Я включив вихід у свій ОП під розділом редагування.
Агуевара
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.