Сортировка по регулярным выражениям

У меня есть набор регулярных выражений POSIX *

^BEGIN:VCARD\r$ ^VERSION[^AZ] ^FN[^AZ] ^N[^AZ] ^NICKNAME[^AZ] ^EMAIL[^AZ] ^X-\([AZ-]*\) ^TEL[^AZ] ^ADR[^AZ] ^ORG[^AZ] ^TITLE[^AZ] ^BDAY[^AZ] ^URL[^AZ] ^ROLE[^AZ] ^NOTE[^AZ] ^END:VCARD\r$ 

и файл с строками, каждый из которых соответствует одному из регулярных выражений:

 BEGIN:VCARD VERSION:3.0 N:Doe;Jane;;Ms; URL:http://janedoe.com/ EMAIL:jdoe@example.org EMAIL:jane.doe@janedoe.com BDAY:1970-01-01 X-JABBER:jane.doe@example.org X-ICQ:1234567890 END:VCARD - BEGIN:VCARD VERSION:3.0 N:Doe;Jane;;Ms; URL:http://janedoe.com/ EMAIL:jdoe@example.org EMAIL:jane.doe@janedoe.com BDAY:1970-01-01 X-JABBER:jane.doe@example.org X-ICQ:1234567890 END:VCARD - BEGIN:VCARD VERSION:3.0 N:Doe;Jane;;Ms; URL:http://janedoe.com/ EMAIL:jdoe@example.org EMAIL:jane.doe@janedoe.com BDAY:1970-01-01 X-JABBER:jane.doe@example.org X-ICQ:1234567890 END:VCARD 

Я бы хотел сортировать эти строки в соответствии с

  1. номер строки совпадения регулярных выражений (так что строки, начинающиеся с FN, поступают до строк, начинающихся с N),
  2. (так, чтобы X-ABC появился до X-DEF)

В идеале, другие части линий не должны сортироваться (поэтому последовательность строк, начинающихся с EMAIL, должна быть оставлена ​​в покое). Ожидаемый результат должен быть следующим:

 BEGIN:VCARD VERSION:3.0 N:Doe;Jane;;Ms; EMAIL:jdoe@example.org EMAIL:jane.doe@janedoe.com X-ICQ:1234567890 X-JABBER:jane.doe@example.org BDAY:1970-01-01 URL:http://janedoe.com/ END:VCARD - BEGIN:VCARD VERSION:3.0 N:Doe;Jane;;Ms; EMAIL:jdoe@example.org EMAIL:jane.doe@janedoe.com X-ICQ:1234567890 X-JABBER:jane.doe@example.org BDAY:1970-01-01 URL:http://janedoe.com/ END:VCARD - BEGIN:VCARD VERSION:3.0 N:Doe;Jane;;Ms; EMAIL:jdoe@example.org EMAIL:jane.doe@janedoe.com X-ICQ:1234567890 X-JABBER:jane.doe@example.org BDAY:1970-01-01 URL:http://janedoe.com/ END:VCARD 

Существует ли для этого инструмент?

Изменить: Результирующая реализация основана на ответе Ларса Рорбаха .

* Это последовательность свойств vCard в файле экспорта контактов Gmail.

2 Solutions collect form web for “Сортировка по регулярным выражениям”

Обычная команда sort не предоставляет включенного способа указать ваш конкретный «словарь», и, хотя команда grep позволяет вам предоставить файл регулярных выражений, он не изменит порядок вывода. Но вы можете объединить оба в простой цикл foreach – вот пример, который работает в оболочке bash:

 for i in `cat fileofregexp`; do grep "$i" myinputfile; done 

Это берет каждую строку регулярного выражения из вашего файла регулярных выражений по одному и выводит любое соответствие из вашего входного файла, поэтому результирующий вывод будет отсортирован по вашему порядку регулярного выражения. Обратите внимание, что любые строки в вашем файле ввода, которые не совпадают вообще, не будут поступать на выход.

Приложение: в соответствии с запросом, вот версия с использованием цикла while:

 while IFS= read -ri; do grep "$i" myinputfile; done < fileofregexp 

Это не совсем то, как вы создавали его, но, учитывая вашу фактическую цель, было бы проще захватить часть перед двоеточием и отсортировать ее. Вот сценарий Perl, который накапливает строки из отдельных ключей сортировки в отдельных записях массива и сбрасывает vcard, когда он достигает конца.

 #!/usr/bin/perl -n BEGIN { @headers = qw(BEGIN VERSION FN N NICKNAME EMAIL X- TEL ADR ORG TITLE BDAY URL ROLE NOTE END); for $h (@headers) { $data{$h} = ""; } } if (/^([^:]+):/) { $data{exists $data{$1} ? $1 : "X-"} .= $_; if ($1 eq 'END') { for $h (@headers) { print $data{$h}; $data{$h} = ""; } } } else { print; } 

И если вам действительно нужна полная гибкость регулярного выражения, повторите повторное выражение вместо поиска ключа в хеше.

 #!/usr/bin/perl -n BEGIN { @regexps = qw(^BEGIN:VCARD\r$ ^VERSION[^AZ] ^FN[^AZ] ^N[^AZ] ... ^END:VCARD\r$); for $r (@regexps) { $data{$r} = ""; } } for $r (@regexps) { next unless $_ =~ $r; $data{$r} .= $_; last; } if ($_ =~ $regexps[@regexps-1]) { for $r (@regexps) { print "++", $data{$r}; $data{$r} = ""; } } 
  • Как сортировать коллекцию строк из разных файлов?
  • Сортировка файла с целым числом в круглых скобках без пробела
  • сортировать вывод по столбцу
  • Сортировка блоков линий
  • Поддерживает ли сортировка сортировку файла на месте, например `sed --in-place`?
  • Скрипт, который будет читать 5 чисел, а затем сортировать с самого высокого на самый низкий
  • сортировать часть файла
  • Сортировка на основе поля1, field2, но сохранение поля 1 сортировки и игнорирование нулей / пробелов во 2-й сортировке
  • Как сортировать файлы в каталоге на основе номера индекса файла?
  • выбор строк, имеющих одинаковое значение
  • Как найти только каталоги и отсортировать их по размеру
  • Как отсортировать файл на основе раздела поля
  • Linux и Unix - лучшая ОС в мире.