Сортировка файла по полю, начинающемуся со строки

Предположим, у меня есть файл с такой структурой

/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

То есть в алфавитном порядке, в соответствии со строкой Автор -...

Как вы можете видеть положение Автор -... не постоянный.

Как я могу это сделать?

1
задан 13 June 2021 в 20:17

2 ответа

Хотя для данного примера это излишне из-за решения , предложенного в ответе user68186 , в более общем случае вы могли бы сделать что-то вроде этого в 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

Обратите внимание, что оно сортируется в соответствии с лексическим значением все после последнего / - поэтому, если формат Автор- <имя автора> - <название>. <расширение> , это будет

  • фиксированная строка Автор - (не действует, так как имеет одинаковый вес для всех строк); затем
  • <имя автора> - ; затем
  • <название>. ; then

Это похоже на то, как GNU sort работает простой KEYDEF -t- -k2 , т.е. эффективный ключ сортировки начинается с <имя автора> и продолжается до конца строки.

Явный разделитель опущен в вызовах 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 , чтобы вставить «отсутствующий» разделитель, а затем, возможно, использовать подпрограмму регулярного выражения () вместо более простого $ 1 = "" для удаления ведущего элемента.

Это не только потенциально более быстрое / более эффективное использование памяти, чем чистое решение gawk , но и позволяет напрямую добавлять другие параметры sort , например. cmd = "sort -d -t" FS "-k1,1r" .

3
ответ дан 28 July 2021 в 11:31

Попробуйте следующую команду 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. Вторая колонка находится между первой и второй -, то есть Артемида.
  • -o output.txt перенаправляет отсортированные выходные данные в файл, а не в терминал.

Надеюсь, это поможет

3
ответ дан 28 July 2021 в 11:31

Другие вопросы по тегам:

Похожие вопросы: