Eu tenho:
bananaOPENqwertyCLOSErandomtextOPENgrapesCLOSEwhateverOPENsunshineCLOSEgreymoon
esta linha poderia ter muito mais strings OPEN e CLOSE nela.
Desejo imprimir a linha inteira apenas com o que estiver entre qualquer OPEN e CLOSE consecutivos e descartar qualquer outra coisa. ou seja, eu quero a saída assim:
qwertygrapessunshine
o mais próximo que consigo pensar é:
sed -n 's/OPEN\(.*\)CLOSE/\1/g;p'
o que obviamente não funciona.
Como
sed
as correspondências são "gananciosas" (mais precisamente, mais à esquerda), isso é complicado. Tentar:O acima foi testado no GNU
sed
. Se você estiver em BSD/MacOS, provavelmente serão necessárias algumas alterações menores, mas irritantes.Como funciona
Lembre-se de que sed, por padrão, lê uma linha por vez em seu espaço padrão. Isso significa que, quando começarmos a processar um espaço padrão, ele nunca conterá um caractere de nova linha. Assim, podemos usar um caractere de nova linha,
\n
, como um marcador sem possibilidade de ambiguidade.s/OPEN/\n/g
Substituir
OPEN
por novas linhasPor padrão,
sed
lê apenas uma linha por vez em seu espaço padrão. Isso significa que o espaço padrão nunca terá, por conta própria, um caractere de nova linha.s/[^\n]*\n//
Remova tudo antes do primeiro
OPEN
(que agora é uma nova linha).Observe que
[\n]*
corresponde a zero ou mais de qualquer coisa, exceto um caractere de nova linha. Conseqüentemente,[^\n]*\n
corresponde a zero ou mais de qualquer coisa, exceto uma nova linha seguida por uma nova linha. Isso significa que corresponde até e incluindo a próxima nova linha. Por outro lado, como as expressões sed são "gananciosas" (mais à esquerda),.*\n
corresponde a qualquer coisa até e incluindo a última nova linha no espaço padrão.s/CLOSE[^\n]*\n//g
Remova tudo começando
CLOSE
e indo para a próxima nova linha.s/CLOSE.*$//
Retire do último
CLOSE
ao final da linha.