sed -ne'/pattern1/{:1' -e'$p;N;s/\n/&/[num]; to' -eb1 -e\} \
-e'/pattern2/{:2' -e'$p;N;s/\n/&/[num]; to' -eb2 -e\} \
-ed -e:o -eh -e'y/\n-/-\n/;s/[^-]*//g' -e'H;x;p'
Isso imprimirá quantos -
traços após um bloco de correspondência, pois há novas linhas que seguem essa correspondência. E assim, se você quisesse 4 linhas após cada partida de pattern1 e 2 após cada partida de pattern2, você obteria uma linha divisória adicional impressa entre cada bloco de 4 hífens na cauda de um bloco de padrão1 e 2 hífens na cauda de um padrão2 quadra. Isso é tudo verdade exceto quando a última linha é encontrada ao coletar a cauda de cada uma - nesse caso, tudo entre a última linha e a correspondência de padrões é impresso, mas nenhum hífens é acrescentado.
Você pode notar que grande parte do código no script sed
acima é bastante redundante. Basicamente, estamos apenas implementando um tipo idêntico de loop para cada correspondência possível. É graças às regras de sintaxe muito simples de sed
, como é evidenciado acima, que torna o script sed
tão eminentemente programável. Em outras palavras, como a sintaxe do sed
é básica, é um assunto simples escrever um script que possa escrever um script sed
.
Por exemplo, esta tarefa pode ser facilmente parametrizada para funcionar com qualquer número de padrões e contagens de linha de acompanhamento associadas:
amatch(){ sed ${2:+"-ne$(n=0; \
while [ "$#" -gt "$((!!(n+=1)))" ]; \
do printf "\n/%s/{:$n\n\t%s;to\n\t%s\n}" \
"$1" "\$p;N;s/\n/&/$2" "b$n"; \
shift 2; \
done; printf "\nd;:o\n\t%s\n\t%s\n\tH;x;p" \
'h;y/\n-/-\n/' 's/[^-]*//g' \
)"}; }
Contanto que amatch()
seja chamado com 2 ou mais parâmetros, ele criará um script sed
exatamente como o acima, e escreverá um loop para cada par.
Primeiramente, ele cria e imprime um script sed
em um subshell e, depois, sed
o executa contra stdin.
Então, quando eu faço:
seq 30 | amatch \[45] 5 1$ 2
O laço while do shell monta e imprime para o comando substituir um script que se pareça com:
/[45]/{:1
$p;N;s/\n/&/5;to
b1
}
/1$/{:2
$p;N;s/\n/&/2;to
b2
}
d;:o
h;y/\n-/-\n/
s/[^-]*//g
H;x;p
E sed
avalia isso contra stdin e imprime ...
1
2
3
--
4
5
6
7
8
9
-----
11
12
13
--
14
15
16
17
18
19
-----
21
22
23
--
24
25
26
27
28
29
-----