У меня есть RDF-файл с блоками данных различного числа строк, обозначенных <
и />
. Внутри каждого блока есть поле, обозначенное как name="some name"
. Мне нужно отсортировать блоки по значению name
без изменения порядка какой-либо из строк в каждом блоке. Кроме того, в каждом блоке есть поле с номером. Мне нужно изменить нумерацию этих полей от 1 до n в зависимости от отсортированной позиции каждого блока.
Вот пример из 3 блоков:
Число, на которое я ссылался, – это число, следующее за $CHROME
в приведенном выше примере. Я старый ассемблер, COBOL, Fortran, программист на Basic, но я не собираюсь разбираться со скриптами или более новыми языками. Я мог бы, вероятно, сделать это в программе Basic, но я бы хотел решение Linux, если это возможно.
Я надеюсь, что есть какой-то символ – или, по крайней мере, некоторая строка – которая никогда не появится в вашем файле. Я предполагаю, что это верно для |
, Для большей безопасности я буду использовать ||
,
Запустите эту команду:
sed -n -e H -e '/ ^ * \ /> * $ / {s /.*//; Икс; s /.* НС1: имя = "\ ([^"] * \) / \ 1 & /; s / \ n / || / gp} ' your_file \ | Сортировать \ | нл -ба \ | sed -e 's / * \ ([0-9] * \) [^ |] * || \ (. * RDF: about = "rdf: # $ CHROME \) [0-9] * / \ 2 \ 1 / '-e' s / || / \ n / g '
Примечание: это (вероятно) требует наличия GNU sed.
sed
чтобы преобразовать файл в формат, подходящий для сортировки (подробности ниже). sed
. nl -ba
, но cat -n
будет работать так же хорошо, и, возможно, есть другие варианты. sed
чтобы убрать номер строки с начала строки и вставить его после CHROME
. Разберите данные обратно в исходный формат. sed
Команда sort
обрабатывает каждую строку как запись. Поэтому мы берем каждую (разделенную) запись из вашего входного файла и объединяем все строки, образуя одну длинную строку. Мы также копируем значение name
в начало строки, чтобы избежать необходимости указывать ключ сортировки.
-n
чтобы отключить автоматическую печать. Линии будут напечатаны только тогда, когда мы скажем p
. Выполните H
в каждой строке. Это добавляет текущую строку в область удержания. Логически, возможно, имеет смысл скопировать строку <
в пространство удержания (с помощью команды h
), а затем добавить все последующие строки. Я произвольно выбрал этот подход.
Обратите внимание: поскольку мы добавляем строку <
к пустому пространству удержания, в начале агрегированной записи добавляется дополнительная новая строка.
/>
, необязательно с предшествующим и / или сопровождаемым пробелами. Когда мы находим это, мы знаем, что у нас есть полная запись в области удержания. Выполните следующие команды только в этих строках.
s/.*//
очищает пространство шаблона (т. е. стирает строку />
). Это на самом деле не выбрасывает какую-либо информацию; строка />
уже была добавлена в область удержания (потому что каждая строка добавляется в область удержания). x
меняет пространство образца и пространство удержания. Это извлекает агрегированную (добавленную / объединенную) запись из пространства удержания в пространство образца. Из-за предыдущей ( s/.*//
) команды это очищает пространство удержания. s/.*NS1:name="\([^"]*\)/\1&/
ищет поле имени и копирует его значение в начало записи. Это не удастся, если вы можете иметь имя с символами кавычек в нем. s/\n/||/gp
заменяет каждую новую строку в пространстве шаблонов на ||
, (Это шаг, который преобразует запись в одну строку.) Из-за p
печатается запись. Вывод первой команды sed
при запуске в файле примера
AAA Carolinas|| Adobe Forums|| Adorama||
sed
s/ *\([0-9]*\)[^|]*||\(.* RDF:about="rdf:#$CHROME\)[0-9]*/\2\1/
прерывает линия на куски:
\1
. name
и ||
после этого. RDF:about="rdf:#$CHROME
. Это становится группой \2
. Затем он заменяет первые пять частей на RDF:about="rdf:#$CHROME
и номер строки (номер новой записи). Поскольку остальная часть записи не была сопоставлена, команда не влияет на нее.
s/||/\n/g
заменяет каждый ||
с новой строкой, восстановление (воссоздание) исходной многострочной структуры файла. … Чтобы отправить вывод в файл, добавьте > your_output_file
в самом конце последней строки команды (т. > your_output_file
конце второго sed
). Затем вы можете переместить ( mv
) your_output_file
в исходный файл. Нет никакого смысла указывать параметр --output=
(или -o
) для команды sort
; вывод из sort
должен идти в команду, которая применяет номера строк. Если вы хотите захватить промежуточный файл, скажите так.