Ниже приведена простая awk
программа, которая предполагает, что данные выглядят точно так же, как вы показываете, т. е. что
{
, ;
, и что }
встречается в строках, на которых больше ничего нет. Он использует стек для отслеживания того, с каким тегом он работает в данный момент, и помещает в стек новые теги, когда они встречаются во входных данных. Когда найден }
, выводится конечный тег для вершины стека. Строки данных обнаруживаются по тому факту, что они не заканчиваются ни одиночным символом {
, ни символом }
.
Никаких попыток проверки данных не предпринимается.
$NF == "{" {
stack[++top] = $1 # push tag to stack
printf "<%s>\n", stack[top] # output opening tag
next
}
$NF == "}" {
printf "</%s>\n", stack[top--] # output closing tag + pop stack
next
}
{
sub(";$", "", $2) # remove ; from EOL
printf "<%s>%s</%s>\n", $1, $2, $1 # output tag with data
}
Для вашего примера данных awk -f script.awk data.in
дает
<unknown-applications>
<unknown-tcp>
<destinations-per-hour>10</destinations-per-hour>
<sessions-per-hour>10</sessions-per-hour>
<session-length>
<maximum-bytes>100</maximum-bytes>
<minimum-bytes>50</minimum-bytes>
</session-length>
</unknown-tcp>
<unknown-udp>
<destinations-per-hour>10</destinations-per-hour>
<sessions-per-hour>10</sessions-per-hour>
<session-length>
<maximum-bytes>100</maximum-bytes>
<minimum-bytes>50</minimum-bytes>
</session-length>
</unknown-udp>
</unknown-applications>
, который при прогоне через xmlstarlet fo
превращается в
<?xml version="1.0"?>
<unknown-applications>
<unknown-tcp>
<destinations-per-hour>10</destinations-per-hour>
<sessions-per-hour>10</sessions-per-hour>
<session-length>
<maximum-bytes>100</maximum-bytes>
<minimum-bytes>50</minimum-bytes>
</session-length>
</unknown-tcp>
<unknown-udp>
<destinations-per-hour>10</destinations-per-hour>
<sessions-per-hour>10</sessions-per-hour>
<session-length>
<maximum-bytes>100</maximum-bytes>
<minimum-bytes>50</minimum-bytes>
</session-length>
</unknown-udp>
</unknown-applications>
Это то же самое, как если бы у нас были строки, но теперь у нас есть абзацы. Разобрать два файла, подставить в хеш абзацы первого, а для второго абзаца вывести только если его нет.
awk -v RS="" -v ORS="\n\n" 'FNR==NR{a[$0]; next} !($0 in a)' a.bib b.bib
Выход:
@InProceedings{,
title = {This Is My Father's World Standard Tuning Traditional Fast Tempo - “Thumbpicking” Style Arrangement by Mark Hanson},
year = {2005},
file = {:MyFathersWorld_p2.pdf:PDF},
groups = {Solo Tab},
}
Будьте осторожны, потому что пустой символ в любом месте может привести к потере дубликатов. Возможно, вы хотели бы запустить некоторые diff
вместе, чтобы подтвердить результаты.