Вот решение, которое решает общую проблему, предполагая, что нужно выбрать диапазон элементов на основе «линеаризации» HTML.Это решение использует pup
для преобразования HTML в JSON, а затем использует jq для выполнения линеаризации, выделения и преобразования обратно в HTML.
program.jq
Идея состоит в том, чтобы «линеаризовать» HTML, рекурсивно поднимая дочерние элементы на верхний уровень:
# Emit a stream by hoisting .children recursively.
# It is assumed that the input is an array,
# and that .children is always an array.
def hoist:
.[]
| if type == "object" and has("children")
then del(.children), (.children | hoist)
else .
end;
def indexof(condition):
label $out
| foreach .[] as $x (null; .+1;
if ($x|condition) then .-1, break $out else empty end)
// null;
# Reconstitute the HTML element
def toHtml:
def k: . as $in | (keys_unsorted - ["tag", "text"])
| reduce .[] as $k (""; . + " \($k)=\"\($in[$k])\"");
def t: if .text then .text else "" end;
"<\(.tag)\(k)>\(t)</\(.tag)>"
;
# Linearize and then select the desired range of elements
[hoist]
| indexof( .tag == "iframe") as $first
| indexof( .tag == "div" and .id=="trend") as $last
| .[$first:$last]
| .[]
| toHtml
Вызов:
pup 'json{}' < input.html | jq -rf program.jq
Вывод:
<iframe></iframe>
<div class="text">TEST</div>