Если вы хотите сделать только один проход в файле и свести к минимуму количество строк, хранящихся в памяти, вы можете использовать awk
с подходом конечного автомата.Это не самые короткие решения, но их легко придумать и читать/обслуживать. Вы можете заменить имена состояний числами, чтобы сделать его (возможно )более эффективным.
PATTERN1=pattern1 PATTERN2=pattern2 awk '
BEGIN {
p1 = ENVIRON["PATTERN1"]
p2 = ENVIRON["PATTERN2"]
state = "init"
}
state == "init" {
if ($0 ~ p2) state = "p2_found"
print
next
}
state == "p2_found" {
if ($0 ~ p1) {
state = "p1_found"
p1_line = $0
printf "%s", hold
hold = ""
} else if ($0 ~ p2) {
# we can print the text held since the last p2
printf "%s", hold
hold = $0 RS
} else hold = hold $0 RS
next
}
state == "p1_found" {
if ($0 ~ p2) {
state = "p2_found"
# the line that matched p1 is not discarded
printf "%s\n%s", p1_line, hold;
hold = ""
}
hold = hold $0 RS
}
END {
# here we are not printing p1_line which is how it is discarded
printf "%s", hold
}'
(Я предполагаю, что нет строк, соответствующих как pattern1
, так иpattern2
).