2015-08-05 2 views
1

Имейте большой документ HTML, где термин «BEGIN» и «END» повторяются по всему документу. Например, BEGIN - <script>, а END - </script>. Для каждого экземпляра шаблона в документе есть переменное количество строк между шаблоном (между <script> и </script>).Как удалить строки между рисунком при повторении рисунка

Пытался следующее sed:

sed '/\<script>/,/\<\/script>/d' 

Этой sed строки удаляет все между первым вхождением <script> и появлением </script> в прошлом.

попытался также:

awk '/\<script>/,/\<\/script>/d' 

Эта awk строка удаляет все содержимое между рисунком, но, в отличие от SED строки, сохраняет каждое вхождение шаблона, как это:

<script> 
</script> 

В целом, я может получить вариант того, что я хочу (или его противоположность).

  • СЭД удаляет текст между (один экземпляр) шаблон
  • AWK поддерживает все вхождения шаблона, но удаляет содержимое между узором, а также содержание до и после образца.

Мой вопрос: с помощью патч в или AWK (и/или любой другой утилиты GNU), как удалить содержимое между шаблоном, когда термины для определения (информация с BEGIN термин и END термин) встречаются несколько раз в документе?

+1

'\ <' соответствует пустой строке в начале слова. Нет необходимости скрывать символ '<' в sed. – potong

+1

Никогда не используйте выражения диапазона, поскольку они делают тривиальные задания очень незначительными, но затем требуют полного переписывания и/или дублирования условий, когда проблема становится еще немного интереснее. Всегда используйте флаги, например. 'awk '/ start/{f = 1} f;/end/{f = 0} 'file' –

ответ

1

Другой AWK альтернатива

awk '/\<script/{p=1};/\/script/{p=0;;next}; !p' file.html 
+0

spot on! TY. Не могли бы вы принять еще один момент, чтобы задокументировать ваше решение? Несколько других на этой странице приложили добрые усилия, чтобы помочь, но я не мог сделать их предложения работать. Если у вас есть мнение, почему - это было бы полезно знать. В общем, я обнаружил, что 'awk' более надежен, чем' sed' и 'join'. –

+1

Осторожно там -' \ <'- это буквальный' <', предшествующий бесполезной обратной косой чертой в некоторых awks и разделитель границ слов в другие. Я подозреваю, что вы просто хотите '<', а не '\ <'. Также очистите избыточное ';' s. –

+1

@JayGray идея состоит в том, чтобы использовать флаг 'p', чтобы указать, что вы находитесь в теге скрипта или нет. '! p' должен печатать, когда вы не внутри сценария. Обратите внимание, что этот скрипт не является надежным и может быть не переносимым. – karakfa

0

sed работает для меня. Вы уверены, что удалили все между первым и последним вхождением?

for i in {1..20} ; do 
    echo $i 
    ((0 == i % 7)) && echo '<script>' 
    ((0 == i % 8)) && echo '</script>' 
done | sed '\=<script>=,\=</script>=d' 

Выход:

1 
2 
3 
4 
5 
6 
7 
9 
10 
11 
12 
13 
14 
17 
18 
19 
20 

Чтобы увидеть снятые детали, добавьте ! перед d:

... | sed '\=<script>=,\=</script>=!d' 
<script> 
8 
</script> 
<script> 
15 
16 
</script> 
+0

Это грозный пример. Но я могу подтвердить, что в моем документе '' '' 'sed', кажется, теряется след первого появления инструкции END (т. Е.' ') и удаляется до конца документа. Мой запрос заключается в том, что вы выбираете свой любимый HTML-документ с несколькими объявлениями javascript и видите, можете ли вы удалять только множественное вхождение этих объявлений, включая операторы открытия и закрытия ('') –

+0

ОК, я пробовал: 'sed '/ \ 'до END (на ваш пример). Затем я запускал 'sed '/ BEGIN /,/END/d'' (не! D). Этот набор изменений работает. Это боль в заднице, но я мог применить вышеупомянутое изменение к более крупному файлу HTML. Надеясь, что кто-то видит причину, почему 'sed' не может правильно обработать правильно экранированные версии' '. –

0

Попробуйте с:

awk '/<script>/,/<\/script>/{next}1' 
+0

Получаем результат как строка 'sed'. В частности, строка' awk' удаляет все данные после первого появления '

2
$ cat file 
a 
<script> 
b 
</script> 
c 
<script> 
d 
</script> 
e 

$ awk '/<script>/{f=1} !f; /<\/script>/{f=0}' file 
a 
c 
e