Для набора номеров строк … Извлеките контент между первым и последним появлением разных шаблонов

У меня есть аналогичный контент в файле. У меня есть список номеров строк со мной, скажем 1,2, 4. Мне нужна помощь по нижеуказанным требованиям

  1. Может подавать все необходимые строки #s
  2. Извлеките содержимое между первым входом и последним появлением </book>

Не могли бы вы мне помочь. Надеюсь, я написал ясно. Если есть какие-либо вопросы, прокомментируйте это. Я уточню это. Заранее спасибо за вашу помощь.

Данные:

 </p><p>abc</p></book><book><p style="text-indent:0em;">def</p></book><book><p>ghi</p><p style="text-indent:0em;"></book><book><div><p> </div><p>123</p></book><book><p style="text-indent:0em;">456</p><p>789</p><p style="text-indent:0em;"></book><book><div><p> <div><p>nothing !!!</p></div> </p><p>ABC</p></book><book><p style="text-indent:0em;">DEF</p></book><book><p>GHI</p><p style="text-indent:0em;"></book><book><div><p>JKL</p></div></book><div> 

Входная строка #s: 1, 2, 4 (которую я хочу подавать в команде)

Желаемый результат:

 <book><p style="text-indent:0em;">def</p></book><book><p>ghi</p><p style="text-indent:0em;"></book> <book><p style="text-indent:0em;">456</p><p>789</p><p style="text-indent:0em;"></book> <book><p style="text-indent:0em;">DEF</p></book><book><p>GHI</p><p style="text-indent:0em;"></book><book><div><p>JKL</p></div></book> 

2 Solutions collect form web for “Для набора номеров строк … Извлеките контент между первым и последним появлением разных шаблонов”

1) Извлечь определенные линии

В примере с четырьмя линиями для извлечения 1, 2 и 4 строки будет легко удалить третью строку:

 sed 3d file 

Но ваш файл, вероятно, более сложный, поэтому более общее решение было бы сделать

 sed -e 1b -e 2b -e 4b -ed file 

Поэтому для каждой строки, которую нужно сохранить, вы переходите к концу скрипта с помощью b и удаляете все остальные файлы.

Для более длинного списка номеров строк вы можете сгенерировать скрипт:

 sed $(for i in 1 2 4; do echo "-e ${i}b"; done) -ed file 

Но, похоже, речь идет не о номерах строк, а о том, есть ли <book> s на этой строке. Если это правда, вам лучше забыть о номерах строк и сделать

 sed '/<book>/!d' 

2) извлечение содержимого

Greedy * regexp не является другом для таких задач. Вот почему у моей личной версии sed есть опция o для команды s чтобы заменить ее совпадающей частью:

 sed '/<book>/!d;s_<book>.*</book>_&_o' 

Но это не сработает для вас, так что вам нужно еще несколько жонглировать регулярным выражением:

 sed '/<book>/!d;s_<book>_\n&_;s_.*\n__;s_\(.*</book>\).*_\1_' file 

Если ваша версия sed не поддерживает \n в заменяющей строке, используйте фактическую строку новой строки (экранированную обратной косой чертой):

 sed '/<book>/!d;s_<book>_\ &_;s_.*\n__;s_\(.*</book>\).*_\1_' file 

С perl :

 #!/usr/bin/env perl use strict; use warnings; use v5.10; my @lines = (1, 2, 4); while(<>) { next unless $. ~~ @lines; chomp; s#.*?(<book>.*</book>).*#$1#; say } 
Linux и Unix - лучшая ОС в мире.