#bash #shell #awk #sed #grep
#bash #оболочка #awk #sed #grep
Вопрос:
У меня есть HTML-код, как показано ниже:
<html>
<head>
<style>
table, th, td {
border:1px solid black;border-collapse:collapse
}
</style>
</head>
<body>
<table style=width:30%>
<tr>
<td>version2</td>
<td>FAIL</td>
</tr>
<tr>
<td>version1</td>
<td>FAIL</td>
</tr>
<tr>
<td>version6</td>
<td>PASS</td>
</tr>
Всякий раз, когда я вижу, что ключевое слово НЕ работает в тегах, мне нужно заменить приведенный выше код, как показано ниже. Для ПРОХОЖДЕНИЯ ничего не нужно делать.
<html>
<head>
<style>
table, th, td {
border:1px solid black;border-collapse:collapse
}
</style>
</head>
<body>
<table style=width:30%>
<tr bgcolor="red">
<td>version2</td>
<td>FAIL</td>
</tr>
<tr bgcolor="red">
<td>version1</td>
<td>FAIL</td>
</tr>
<tr>
<td>version6</td>
<td>PASS</td>
</tr>
Используя sed, я могу выполнить поиск слова и заменить его, используя команду ниже:
sed -i 's/<tr>/<tr bgcolor="red">/g'
Но в моем случае сначала мне нужно выполнить поиск по ключевому слову FAIL, затем этот конкретный <tr>
тег необходимо заменить.
Комментарии:
1. Извините, невозможно анализировать XML-файлы с помощью регулярных выражений с помощью sed. Используйте инструменты, поддерживающие xml. Например, xmllint .
2. Не то чтобы это было совершенно невозможно; вы могли бы написать симулятор самолета
sed
, если бы действительно очень захотели. Но вы этого не делаете.
Ответ №1:
Используя GNU awk, чтобы определить разделитель записей из нескольких символов:
awk -v RS='<tr>' 'NR > 1 { rs = /FAIL/ ? "<tr bgcolor="red">" : RS } { printf "%s%s", rs, $0 }' file
При этом <tr>
в качестве разделителя записей используется открывающий тег, который заменяет его, если /FAIL/
соответствует какой-либо части записи.
Мы используем NR > 1
так, чтобы это начиналось только после первой записи, чтобы избежать получения дополнительного <tr>
значения в начале вывода. Для первой записи (все, вплоть до первой <tr>
во входных данных), rs
остается неустановленным, поэтому при печати будет отображаться пустая строка.
Комментарии:
1. @Fenech, с помощью приведенного выше кода он заменяется на тег ключевого слова FAIL вместе с указанным выше тегом ключевого слова PASS.
2. Я запустил его с вашим образцом ввода, и он только изменил
<tr>
содержимоеFAIL
. Возможно, ваш реальный ввод немного отличается?3. @Rama Я только что понял, что в моем ответе была ошибка, и она добавляла a
<tr>
в начало вывода. Сейчас я это исправил.
Ответ №2:
awk 'BEGIN {
RS="<tr>|</tr>"
}
$0 ~ /FAIL/ {
print "<tr bgcolor="red">"$0"</tr>"
}
$0 ~ /PASS/ {
print "<tr>"$0"</tr>"
}
!/PASS/ amp;amp; !/FAIL/ {
print $0
}' html
Одна строка:
awk 'BEGIN { RS="<tr>|</tr>" } $0 ~ /FAIL/ { print "<tr bgcolor="red">"$0"</tr>" } $0 ~ /PASS/ { print "<tr>"$0"</tr>" } !/PASS/ amp;amp; !/FAIL/ { print $0 }' html
Используя awk с файлом с именем html, установите разделитель записей на открывающий или закрывающий теги tr, затем выполните поиск в записи ($ 0) на предмет сбоя при печати тегов tr с $ 0 соответственно. Сделайте то же самое для PASS.
Комментарии:
1. он работает нормально, но не распознает HTML-код, отличный от тегов <tr> </tr>
2. Ну, в вашем примере не было другого html. Возможно, вы могли бы обновить?
3. Я обновил ответ, чтобы учесть любой другой HTML
4. ОК. Попробуйте сейчас.
5. Спасибо, Раман, но я не полностью понял код.. возникает путаница. Но он работает нормально.. Не могли бы вы, пожалуйста, ознакомить меня с кодом. Я действительно ценю ваши усилия, особенно за 0 долларов.
Ответ №3:
В соответствии с вашими примерами, не могли бы вы попробовать следующий.
tac file | awk '/<td>FAIL</td>/{y=1} y amp;amp; /^<tr>/{print "<tr bgcolor="red">";next} {print}' | tac
Я использую решение tac и awk для того же, где tac будет считывать файл в обратном порядке, а awk будет обрабатывать записи в соответствии с заданным условием. В дополнение к этому, передача вывода awk cmd в tac для получения записей в нужном порядке
Комментарии:
1. с помощью приведенного выше даже для ключевого слова PASS оно также заменяется до тех пор, пока не встретит ключевое слово FAIL.
2. @Rama, я думаю, что этот флаг необходимо отключить, после выполнения условия здесь проблема.
Ответ №4:
Ниже приведено решение, которое буферизует ввод. Он также обрабатывает отступы и пропускает другие элементы HTML.
# if current line starts a table row, save it in tr
$0 ~ "<tr>" { tr = $0; next }
# if we are inside a table row, append it to tr
$0 !~ "</tr>" amp;amp; tr != "" { tr = tr "n" $0; next }
# if current line ends a table row, insert bgcolor if needed
# and print the previously saved tr variable
$0 ~ "</tr>" {
if (index(tr, "<td>FAIL</td>") > 0) {
sub("<tr>", "<tr bgcolor="red">", tr)
}
print tr "n" $0
tr = ""
next
}
# when current line is not inside a table row just print it
{ print }
Если скрипт сохранен в highlight-failing.awk
и HTML в versions.html
, команда может быть вызвана с помощью
awk -f highlight-failing.awk versions.html
Комментарии:
1. в приведенном выше коде, где нам нужно передать наш входной файл.