Предположим, у меня есть файл, структурированный таким образом.
/home/zz/AUTHORBOOKS/Author-Chomsky-Who-Rules-the-World.epub
/home/zz/AUTHORBOOKS/Author-Cioran-Il-nulla.epub
/home/zz/BOOKS/Author-Artemis-Mathematica-Examples.nb
/home/zz/Books/Author-Zigniwe-Hisory-Medicine.pdf
/home/z1/OLDBOOKS1/OLDBOOKS2/Author-Watanabe-Waterloo.pdf
/home/z2/OLDBOOKS1/OLDBOOKS2/Author-Barbero-Lepanto.epub.pdf
Мне бы хотелось, чтобы файл был отсортирован следующим образом:
/home/zz/BOOKS/Author-Artemis-Mathematica-Examples.nb
/home/z2/OLDBOOKS1/OLDBOOKS2/Author-Barbero-Lepanto.epub.pdf
/home/zz/AUTHORBOOKS/Author-Chomsky-Who-Rules-the-World.epub
/home/zz/AUTHORBOOKS/Author-Cioran-Il-nulla.epub
/home/z1/OLDBOOKS1/OLDBOOKS2/Author-Watanabe-Waterloo.pdf
/home/zz/Books/Author-Zigniwe-History-Medicine.pdf
То есть, по алфавиту, согласно строкеAuthor-...
Как видите, положение Author-...
не является постоянным.
Как я могу это сделать?
решение1
Попробуйте следующую bash
команду:
sort -t- -d -k2 -o output.txt input.txt
Он имеет четыре опции плюс имя входного файла input.txt
. Если этот файл отсутствует в текущем каталоге, вам придется указать path/to/the/folder/input.txt
. Опции и их аргументы следующие:
- -t обозначает разделитель полей. Мы используем
-
в качестве разделителя, так что все до и после-
считается отдельными столбцами. - -d указывает на сортировку по словарю. Например, Apple стоит перед Berry.
- -k2 указывает столбец, по которому нужно сортировать, в данном случае второй столбец. Обратите внимание, что первый столбец — это все, что находится перед первым
-
. Например,/home/zz/BOOKS/Author
. Второй столбец находится между первым и вторым-
, то естьArtemis
. - -o
output.txt
перенаправляет отсортированный вывод в файл, а не на терминал.
Надеюсь это поможет
решение2
Хотя для данного примера это излишне из-зарешение, предложенное в ответе пользователя 68186, в более общем случае в GNU awk можно сделать что-то вроде этого:
gawk -F/ '
function mycmp(i1,v1,i2,v2) {
m = split(v1,a);
n = split(v2,b);
return a[m]"" > b[n]"" ? 1 : a[m]"" < b[n]"" ? -1 : 0
}
{
lines[NR] = $0
}
END {
PROCINFO["sorted_in"] = "mycmp";
for(i in lines) print lines[i]
}
' file
Обратите внимание, что сортировка выполняется в соответствии с лексическим значением всего, что находится после последнего /
, поэтому, если формат такой, Author-<author name>-<title>.<extension>
то это будет
- фиксированная строка
Author-
(которая не имеет никакого эффекта, так как имеет одинаковый вес для всех строк); затем <author name>-
; затем<title>.
; затем<extension>
Это похоже на то, как работает sort
простой KEYDEF в GNU -t- -k2
, т.е. эффективный ключ сортировки начинается с <author name>
и продолжается до конца строки.
Явный разделитель опущен в split
вызовах, так что они наследуют значение FS
, что позволяет легко изменить его для систем, использующих другой разделитель пути. Добавленные пустые строки ""
в mycmp
функцию вызывают лексическое сравнение, даже если имена файлов числовые — см., напримерКак awk преобразует строки в числа и наоборот
Если вы предпочитаете использовать эту sort
команду, вы можете воспользоваться возможностями GNU awkДвусторонняя связь с другим процессомк:
- дублировать последнее
/
поле, разделенное -, в начале строки - передать результат
sort
команде - перечитайте отсортированный результат, удалите дублирующийся префикс и распечатайте
то есть
gawk -F/ '
BEGIN {OFS=FS; cmd = "sort -d"}
{print $NF $0 |& cmd}
END {
close(cmd,"to");
while(cmd |& getline){$1 = ""; print};
close(cmd,"from")
}
' file
Здесь есть небольшой обман, поскольку абсолютные пути (строки начинаются с /
) подразумевают изначально пустое поле; для обработки относительных путей вам нужно будет изменить print $NF $0
на print $NF,$0
, чтобы вставить «отсутствующий» разделитель, а затем, возможно, использовать регулярное выражение sub()
вместо более простого $1 = ""
способа удаления начального элемента.
Помимо того, что это решение потенциально быстрее и эффективнее в плане использования памяти , оно также позволяет напрямую добавлять gawk
другие опции, например .sort
cmd = "sort -d -t " FS " -k1,1r"