sed
é muito peculiar sobre r
ead - ele fará isso apenas para a linha que corresponde ao padrão - e sempre fará isso último . sed
não r
extrairá um arquivo para um padrão correspondente se o padrão deixar de corresponder antes de liberar a linha. Pelo menos é assim que eu acho que funciona - eu sou muito bom com sed
mas r
ainda me deixa confuso às vezes.
De qualquer forma, o truque é deixá-lo liberar a linha com o padrão que ele quer - garantindo assim a saída para aquela linha, mas atrasar essa saída pelo menos em uma linha e então editá-la.
Você pode fazer isso com relativa facilidade com N;P;D
- que funcionará em conjunto para avançar o contador de linhas de sed
, pelo menos, uma linha à frente das linhas impressas. Considere os dois arquivos a seguir:
###file1
some string 1
some string 2
some other string
some string 4
some string 5
###file2
some other file
Agora, meu objetivo é realizar uma substituição substituindo o padrão no qual r
ead depende, e para obter r
ead para imprimir seu conteúdo antes da minha alteração é impresso. Aqui está como eu faço:
sed '$!N;s/other \(.*\)\(\n\)/ 3/
/\n.*other/r file2
P;D' file1
OUTPUT
some string 1
some string 2
some other file
some string 3
some string 4
some string 5
Eu também fiz isso com um arquivo diferente2 que imprimia ...
some string 1
some string 2
no trailing newline some string 3
some string 4
some string 5
Eu tenho algumas reservas bastante profundas sobre a portabilidade desse comportamento, mas isso foi com um% GNUsed
, pelo que vale a pena.
Ok, nos comandos acima, sed
está lendo sua entrada uma linha à frente de quando ela é impressa. N
acrescenta a próxima linha de entrada ao espaço padrão, P
imprime até o primeiro caractere \n
ewline no espaço padrão e D
exclui até o primeiro caractere \n
ewline no espaço padrão antes de recomeçar com o que resta. Então, cada linha que vemos impressa é uma linha atrás da visão de sed
- sed
obtém uma janela de duas linhas na entrada.
O padrão que corresponde a r
ead corresponde apenas quando um caractere \n
ewline ocorre antes do qual corresponde ao ciclo em que sed
o puxa pela primeira vez com N
- corresponde apenas ao ciclo em que não o vemos.
A substituição só ocorre quando o \n
ewline ocorre após o padrão - este é o ciclo no qual ele será P
rinted, afinal, mas sed
libera seu buffer de linha e incrementa a linha quando nós puxamos a linha N
ext, então o r
é impresso então e então a substituição ocorre. Meio tedioso, mas eu também sou.
E falando do GNU sed
, ele oferece uma opção bastante interessante para situações como essas, na verdade.
sed '/other/{x;s/.*/cat file2/e;G
s/\(.*\)\n\(.* \)other \(.*\)/ 3/
}' file
info sed
dirá a você ...
-
%código%
Este comando permite que uma entrada pipe de um comando shell em
espaço padrão. Sem parâmetros, o comando 'e' executa o
comando que é encontrado no espaço padrão e substitui o padrão
espaço com a saída; uma nova linha à direita é suprimida.
Também faço um pequeno embaralhamento de espaço de padrão - quero um espaço de padrão em branco no qual executar meu comando e, portanto, alterno para o espaço de retenção não utilizado. Mas é um pouco mais simples de entender, porque você não precisa considerar os tempos de liberação de linha. É, essencialmente, o que já foi sugerido por outros meios, talvez com um pequeno benefício, pois qualquer caractere especial de e [COMMAND]
não gerará um erro se eles existirem no arquivo de leitura de destino.
Ah, a propósito, as impressões acima:
some string 1
some string 2
some other file some string 3
some string 4
some string 5