У меня есть файл, который содержит другой вид текстовых форматов, моя цель состоит в том, чтобы извлечь только часть HTML и создать файл с этим HTML-кодом. Я думаю, что это возможно с grep
или awk
. Мой файл содержит также строки как это:
Sender name `<test@email.com>`
Я записал этот сценарий cat file1.html | grep -E "<[^>]*>"
. Но проблема состоит в том, что это производит также строки как Sender name
, и т.д. Я хочу извлечь содержание только после <html>
тег. Таким образом, это не полезно для меня:
Return-Path: <test@test.com>
for <test@localhost> (single-drop); Thu, 21 Sep 2017 18:34:07 +0400 (+04)
Return-path: <test@test.com>
(envelope-from <test@test.com>)
References: <test@test.com>
From: test user <test@test.com>
X-Forwarded-Message-Id: <test@test.com>
Message-ID: <test@test.com>
In-Reply-To: <test@test.com>
Мы можем достичь этой цели с помощью инструмента sed
- потокового редактора для фильтрации и преобразования текста . Краткий ответ дан под пункт 5 ниже. Но я решил написать подробное объяснение.
0 Сначала давайте создадим простой файл для проверки наших команд:
$ printf '\nTop text\nSender <example@email.com>\n\n<html>\n\tThe inner text 1\n</html>\n\nMiddle text\n\n<HTML>\n\tThe inner text 2\n</HTML>\n\nBottom text\n' | tee example.file
Top text
Sender <example@email.com>
<html>
The inner text 1
</html>
Middle text
<HTML>
The inner text 2
</HTML>
Bottom text
1. Мы можем обрезать все между тегами <html>
и </html>
, включая их, следующим образом:
$ sed -n -e '/<html>/,/<\/html>/p' example.file
<html>
The inner text 1
</html>
Опция -e script
(--expression=script
) добавляет скрипт к командам, которые будут выполнены. В этом случае добавляется скрипт '/<html>/,/<\/html>/p'
. Хотя у нас есть только один скрипт, мы можем опустить эту опцию.
Опция -n
(--quiet
, --silent
) подавляет автоматическую печать пространства шаблона, и наряду с этой опцией мы должны использовать некоторые дополнительные команды, чтобы сообщить sed
, что печатать.
Эта дополнительная команда - команда печати p
, добавленная в конец скрипта. Если sed
не был запущен с опцией -n
, команда p
будет дублировать ввод.
Наконец, двумя запятыми - /<html>/,/<\/html>/
- мы можем указать диапазон. Обратите внимание, что мы используем \
для экранирования специального символа /
, который здесь играет роль разделителя.
2. Если мы хотим обрезать все между тегами <html>
и </html>
, не печатая их, мы должны добавить некоторые дополнительные команды:
$ sed -n '/<html>/,/<\/html>/{ /html>/d; p }' example.file
The inner text 1
Фигурные скобки, {
и }
, используются для группировки команд.
Команда d
удалит каждую строку, которая соответствует выражению html>
.
3. Но наш example.file
также имеет теги <HTML>
верхнего регистра. Таким образом, мы должны сделать регистр соответствия без учета регистра. Мы можем сделать это, добавив флаг /I
к регулярным выражениям:
$ sed -n '/<html>/I,/<\/html>/I{ /html>/Id; p }' example.file
The inner text 1
The inner text 2
I
для сопоставления регулярных выражений является расширением GNU, которое приводит к совпадению REGEXP в без учета регистра. 4. Если мы хотим удалить все теги HTML между тегами <html>
, мы можем добавить дополнительную команду, которая будет анализировать и «удалять» строки, которые начинаются с <
и заканчиваются >
:
sed -n '/<html>/I,/<\/html>/I{ /html>/Id; s/<[^>]*>//g; p }' example.file
Команда s
заменит строки, которые соответствуют выражению /<[^>]*>/
, пустой строкой //
- s/<old>/<new>/
.
Флаг шаблона g
будет применять замену ко всем совпадениям с регулярным выражением, а не только к первому.
Вероятно, мы бы хотели пропустить команду удаления в этом случае:
sed -n '/<html>/I,/<\/html>/I{ s/<[^>]*>//g; p }' example.file
5. Чтобы внести изменения вместо файла и создать резервную копию, мы можем использовать опцию -i
, или мы можем создать новый файл на основе вывода sed
, перенаправив >
вывод в новый file:
sed -n '/<html>/I,/<\/html>/I p' example.file -i.bak
sed -n '/<html>/I,/<\/html>/I p' example.file > new.file
Ссылки: