AWK с RS, не совпадающим с шаблоном (снова спрашиваю, потому что я случайно пометил как решенный. Лучшее объяснение в те времена.)

У меня есть файл odt с пустыми строками между строками текста. Я хочу найти термин и вывести всю группу текста, где есть совпадение с термином. Мой подход заключается в том, чтобы сказать, что пустые строки в файле odt являются разделителями записей. Файлы odt - это zip-архивы с текстом, содержащимся в файле content.xml. После распаковки файла odt я использовал xmllint --format content.xml для вставки новых строк (как показано ниже), а "пустые" строки на самом деле являются строками без текста между > и <. Поэтому я хочу установить RS как любую такую строку, в которой нет текста между > и <. Если отформатированный файл content.xml выглядит следующим образом:

<long line of alphanumerics, slashes, single and double quotes><more or the same><and many more>
      <office:text>
      <text:sequence-decls>
        <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/>
        <text:sequence-decl text:display-outline-level="0" text:name="Table"/>
        <text:sequence-decl text:display-outline-level="0" text:name="Text"/>
        <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
        <text:sequence-decl text:display-outline-level="0" text:name="Figure"/>
      </text:sequence-decls>
      <text:p text:style-name="P1">This is the first line</text:p>
      <text:p text:style-name="P1"/>
      <text:p text:style-name="P1">This is the third line</text:p>
      <text:p text:style-name="P1">and this is some more text that is to be included</text:p>
      <text:p text:style-name="P1"/>
      <text:p text:style-name="P1">This is the sixth. I want it included,</text:p>
      <text:p text:style-name="P1">with this line</text:p>
      <text:p text:style-name="P1">and this one</text:p>
    </office:text>

и код выглядит следующим образом:

$ awk '/line/' RS='\n[ \t]*<[^>]*>\n' file.xml

Весь файл выводится. Но я хочу только:

      <text:p text:style-name="P1">This is the first line</text:p>
      <text:p text:style-name="P1">This is the third line</text:p>
      <text:p text:style-name="P1">and this is some more text that is to be included</text:p>
      <text:p text:style-name="P1">This is the sixth. I want it included,</text:p>
      <text:p text:style-name="P1">with this line</text:p>
      <text:p text:style-name="P1">and this one</text:p>
0
задан 7 October 2020 в 18:46

2 ответа

Отвечая на свой вопрос, вдохновленный steeldriver, я изменил файл перед использованием awk:

sed '/>.*</! s/.*/---/' test.txt > modfile.txt  # overwrites lines matching the pattern with what I will name as the record separator, “---”

Затем я смог извлечь всю запись о совпадениях с $ searchterm

awk "/$searchterm/" RS="---" modfile.txt > results.txt
0
ответ дан 4 January 2021 в 08:20

Ваш подход чреват проблемами. Что наиболее важно, нет очевидного способа ограничить соответствие регулярного выражения основным текстом документа - например, в случае / line / , который будет соответствовать таким тегам, как

(Также существует проблема с вашим RS регулярным выражением, использующим два символа новой строки, что помешает ему правильно обработка соседних разделителей; RS = '\ n ([\ t] * <[^>] *> \ n) +' может исправить это, но я не гарантирую этого).

Вместо,я бы предложил сначала извлечь основной текст документа, а затем затем применить awk в "традиционном" режиме абзаца (т.е. с использованием пустого разделителя записей):

xmlstarlet sel -t -v "//office:body/office:text/text:p" -n content.xml | 
  awk -v RS= '/line/{print $0 ORS}'

или с помощью GNU awk, сохраняя фактические разделители записей как проанализировано:

xmlstarlet sel -t -v "//office:body/office:text/text:p" -n content.xml | 
  gawk -v RS= '/line/{printf $0 RT}'

Вы даже можете полностью опустить промежуточный файл, передав стандартный вывод из unzip -p :

unzip -p somefile.odt content.xml | 
  xmlstarlet sel -t -v "//office:body/office:text/text:p" -n - | gawk -v RS= '/line/{printf $0 RT}'
0
ответ дан 4 January 2021 в 08:20

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

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