сортировка слов по разделам

#sorting #awk #unique #mediawiki

#сортировка #авк #уникальный #медиавики

Вопрос:

У меня есть этот текстовый файл, который мне нужно отсортировать по разделам.

 #cat raw_file.txt

== other info ==
===instructions===
===english words===
this
is
only
test


=== missing words ===

==== include words ====
some
more
words

==== customer name ====
ram
sham
amar
akbar
anthony

==== cities ====
mumbai
delhi
pune


=== prefix ===

the
a
an

 

Если я сортирую его «как есть», то он начинается с 2 знаков равенства, за которыми следуют 3 знака равенства, а затем все слова. Как мне отсортировать слова по разделам отдельно?

 # sort raw_file.txt

== other info ==
=== missing words ===
=== prefix ===
==== cities ====
==== customer name ====
==== include words ====
===english words===
===instructions===
a
akbar
amar
an
anthony
delhi
is
more
mumbai
only
pune
ram
sham
some
test
the
this
words
 

Это формат mediawiki, если это имеет значение. Я сортирую каждый раздел, и это занимает много времени.

 #cat expected_output.txt

== other info ==
===instructions===
===english words===
is
only
test
this

=== missing words ===

==== include words ====
more
some
words

==== customer name ====
akbar
amar
anthony
ram
sham

==== cities ====
delhi
mumbai
pune

=== prefix ===
a
an
the
 

Комментарии:

1. может быть, добавить префикс к каждому разделу, затем выполнить обычную сортировку, а затем отрезать лишний префикс? Я думаю, что гораздо проще использовать что-либо на c / java / python / bash (текст канала для сортировки в подоболочке), чем только awk

Ответ №1:

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

 $ awk 'BEGIN {s="sort"} 
       !NF   {c  } 
       /^=/  {close(s); 
              for(i=1;i<=c;i  ) print ""; 
              c=0; 
              print; 
              next} 
       NF    {print | s}' file
 

будет генерироваться…

 == other info ==
===instructions===
===english words===
is
only
test
this


=== missing words ===

==== include words ====
more
some
words

==== customer name ====
akbar
amar
anthony
ram
sham

==== cities ====
delhi
mumbai
pune


=== prefix ===
a
an
the
 

Ответ №2:

Если вы не беспокоитесь о сохранении пустых строк, вы можете использовать:

 awk '/=/ {c  } {print c 1, $0}' file.txt | sort -n | cut -d' ' -f2- | sed '/^$/d'
>== other info ==
>===instructions===
>===english words===
>is
>only
>test
>this
>=== missing words ===
>==== include words ====
>more
>some
>words
>==== customer name ====
>akbar
>amar
>anthony
>ram
>sham
>==== cities ====
>delhi
>mumbai
>pune
>=== prefix ===
>a
>an
>the
 

Этот подход работает путем добавления номера индекса к каждой строке и увеличения индекса на единицу каждый раз, когда строка содержит ‘=’, затем сортировка сначала по номеру индекса, затем по фактическому слову, затем удаление индекса и удаление пустых строк (которые заканчиваются вверху каждой ‘раздел’ после сортировки).

Редактировать

Я только что видел комментарий @Bing Wang — это в основном то, что он предложил вам сделать

Комментарии:

1. очень полезная идиома decorate-sort-undecorate , также известная как преобразование Шварца.

2. Просто чтобы отметить, что sort -u удалит дубликаты — поэтому используйте это вместо sort -n