Вот командная строка Perl (обратите внимание, что ваша оболочка может потребовать от вас экранирования $
s):
perl -e "print sort {(split '/', $a)[-1] <=> (split '/', $b)[-1]} <>"
Просто перетащите в нее список или, если список находится в файле, поместите имя файла в конец командной строки.
Обратите внимание, что этот сценарий на самом деле не изменяет данные, поэтому вам не нужно быть осторожным с тем, какой разделитель вы используете.
Вот пример вывода:
>perl -e "print sort {(split '/', $a)[-1] <=> (split '/', $b)[-1]} " files.txt /a/e/f/g/h/01-do-this-first /a/b/c/10-foo /a/b/c/20-bar /a/d/30-bob /a/b/c/50-baz /a/e/f/g/h/99-local
Я думаю, что единственным решением было бы использовать awk
:
awk
. Однострочник в perl для изменения порядка полей в строке:
perl -lne 'print join " ", reverse split / /'
Вы можете использовать его один раз, передать вывод в sort, затем передать его обратно, и вы достигнете того, чего хотите. Вы можете изменить / / /
на / +/
, чтобы сжать пробелы. И, конечно, вы можете использовать любое регулярное выражение для разделения строк.
Замените последний разделитель в строке другим разделителем, который иначе не отображается в списке, выполните сортировку по второму полю, используя этот другой разделитель в качестве разделителя sort (1), а затем верните изменение разделителя.
delim=/
new_delim=" "
cat $list \
| sed "s|\(.*\)$delim|\1$new_delim|" \
| sort -t"$new_delim" -k 2,2 \
| sed "s|$new_delim|$delim|"
Проблема заключается в том, чтобы знать, какой разделитель использовать, которого нет в списке. Вы можете сделать несколько проходов по списку, а затем grep для последовательности потенциальных разделителей, но все это довольно неприятно - особенно когда концепция «сортировки по последнему полю строки» выражается так просто, а решение - нет.
Правка: один безопасный разделитель для $ new_delim - NUL, поскольку он не может отображаться в именах файлов, но я не знаю, как поместить символ NUL в сценарий оболочки bourne / POSIX (не bash), а также указать, нужно ли сортировать и sed правильно с этим справится.
#!/usr/bin/ruby
f = ARGF.read
lines = f.lines
broken = lines.map {|l| l.split(/:/) }
sorted = broken.sort {|a, b|
a[-1] <=> b[-1]
}
fixed = sorted.map {|s| s.join(":") }
puts fixed
Если все ответы связаны с perl или awk, то можно решить все на скриптовом языке. (Кстати, сначала я попробовал на Perl и быстро вспомнил, что мне не нравятся списки списков Perl. Хотелось бы увидеть версию от гуру Perl.)
. sort
позволяет вам указать разделитель с параметром -t
, если я хорошо его помню. Чтобы вычислить последнее поле, вы можете сделать что-то вроде подсчета количества разделителей в строке и суммирования одного. Например, что-то вроде этого (с использованием разделителя ":"):
d=`head -1 FILE | tr -cd : | wc -c`
d=`expr $d + 1`
( $ d
теперь содержит индекс последнего поля).
что-то вроде этого
awk '{print $NF"|"$0}' file | sort -t"|" -k1 | awk -F"|" '{print $NF }'