O buffer h
old é bom para armazenar uma linha (ou grupo de linhas) até que algum teste posterior seja verdade. Em outras palavras, é bom para lidar com sequências de dados que você quer sequencial, mas não são ainda seqüenciais - porque permite que você as coloque juntas. Mas também requer muitas cópias entre os dois buffers. Isso não é tão ruim se você está construindo uma série de linhas com comandos H
old - apenas acrescentar - mas toda vez que você e x
mudam os buffers, você copia o todo de um para o outro e vice-versa.
Quando você está trabalhando com uma série de linhas que já são sequenciais e deseja removê-las com base no contexto, o melhor caminho a seguir é com
look- à frente - ao contrário da aparência do por trás . cuonglm faz isso para a segunda metade de sua resposta já - mas você pode usar essa lógica para qualquer forma.
sed '$!N;/\nage.*: 10/P;D' <infile >outfile
Veja, isso anexará a linha de entrada h
ext após um delimitador de linha de código N
incorporado ao espaço de padrão atual em cada linha que for \n
e não !
da última. Em seguida, ele verifica se a linha que acabou de ser extraída corresponde a um padrão e, em caso afirmativo, que $
rints somente até o primeiro P
ewline no espaço de padrão - apenas a linha anterior. Por último, \n
elimina o primeiro D
ewline no espaço padrão e inicia o ciclo novamente. Assim, ao longo do arquivo, você mantém uma aparência de uma linha: adiante sem trocar buffers desnecessariamente.
Se eu alterar o comando apenas um pouco, você poderá ver especificamente como ele funciona - deslizando por cima do arquivo com uma janela de duas linhas. Vou adicionar um comando \n
ook pouco antes do l
:
sed '$!N;/\nage.*: 10/P;l;D'
Name is : sara
Name is : sara\nage is : 10$
age is : 10\nName is : john$
Name is : john\nage is : 20$
age is : 20\nName is : Ron$
Name is : Ron
Name is : Ron\nage is : 10$
age is : 10\nName is : peggy$
Name is : peggy\nage is : 30$
age is : 30$
Essa é a saída. As linhas que terminam em D
são o resultado do comando $
ook - que renderiza uma versão de escape do espaço padrão para stdout. As linhas que não terminam em l
são aquelas que, de outra forma, seriam $
rinted. Como você pode ver, a linha anterior é apenas P
rinted quando a segunda linha no espaço padrão - a linha P
ext como apenas puxada e que segue a N
ewline no espaço padrão - corresponde ao seu padrão. p>
Além das soluções já oferecidas, outra maneira de imprimir apenas as linhas Nome que precedem uma linha idade que não termina em 10:
sed -n '/^Name/N;/ 10$/!s/\nage.*//p'
... que acrescenta apenas um \n
ewline seguido da linha de entrada \n
ext se o espaço de padrão começar com a string Name , e somente N
rints uma linha para saída se espaço padrão não termina com a string 10 e se p
puder com êxito sed
ubstitute a s///
ewline seguido da string age e tudo o que segue até a cauda do espaço padrão. Como não pode haver um \n
ewline no espaço padrão, exceto como resultado de um comando de edição - como \n
ext - o garante que as únicas linhas Nome impressas sejam aquelas imediatamente anteriores a idade linha que não termina na string 10 .
Toda a sintaxe usada na resposta acima é padrão POSIX - deve funcionar como escrito com qualquer N
que suporte o padrão.