В 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и т. Д.

В конечном итоге я пытаюсь объединить PDF-файлы pdftkс чем-то вроде следующего

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

но это не работает, так как моя сортировка неправильная.


Спасибо за все великолепные ответы на это. Как всегда с Unix, есть много разных отличных способов снятия кожи с этой кошки.
НГМ

Ответы:


7

Нечто подобное может делать то, что вы хотите, хотя и немного другой подход:

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

Ага, хороший подход! Это действительно делает то, что я, что, спасибо.
НГМ

60

Вы sortможете иметь возможность сделать это для вас:

sort --version-sort

Выдержка из соответствующей записи в -V, --version-sort natural sort of (version) numbers within text
справочной

Это то, что вам нужно. Но если ваша сортировка не предоставляет эту опцию, взгляните на этот пост: stackoverflow.com/a/4495368/1240018
eventhorizon

30

Для этого конкретного примера вы также можете сделать это:

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

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


Разделение, а затем сортировка по одному полю - это отличный совет, который, я уверен, пригодится в будущем, спасибо.
НГМ

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 и использует sort -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

Да. Я включил вывод в свой OP в разделе редактирования.
Агуэвара
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.