E aqui uma abordagem mais geral, independente do número de arquivos com sed
:
sed '1{x;s/$/_/;x;}
/foo/{x;s/_/ 0_/g;x;}
G;s/^\([a-z]*\) *\([0-9]*\).*\n\(.*_\)\([^_]*\)0//
s/^\([a-z]*\) *\([0-9]*\).*\n\([^_]*\)0_\(.*\)/__/
$! {h;d;}
s/[^_]*_//
y/_/\n/' file*
Isso depende de cada arquivo que começa com a linha foo
, como no seu exemplo.
Dado que você tem conhecimento básico sobre como sed
funciona, espaço de padrão e espaço, aqui vem a explicação:
A idéia principal é construir toda a tabela de saída no espaço de armazenamento. Em cada linha, o espaço de espera contém a tabela nesse ponto junto com uma linha de modelo necessária para novas linhas. Usamos _
como separador de linha durante o processamento. E agora, passo a passo:
1{x;s/$/_/;x;}
Isso inicializa o espaço de espera com um único _
como o início da nossa linha de modelos.
/foo/{x;s/_/ 0_/g;x;}
/foo/
endereça linhas que contêm foo
, o que indica o início de um novo arquivo. Nesse caso, os comandos em {}
são executados: cada linha no espaço de manutenção (linhas reais da tabela e a linha do modelo) obtém 0
anexado. Se, posteriormente, encontrarmos a palavra-chave dessa linha, o 0
será substituído pelo número correto; se a palavra-chave não ocorrer, o 0
permanece.
G;s/^\([a-z]*\) *\([0-9]*\).*\n\(.*_\)\([^_]*\)0//
'G' acrescenta o espaço de espera ao espaço do padrão. O comando s
tem quatro \(\)
seções: A primeira contém a palavra-chave, a segunda o valor, a terceira após a nova linha (portanto, é a tabela anexada do espaço de espera) até a segunda ocorrência da palavra-chave %código%). O quarto contém tudo nessa linha, excluindo o% final
. Portanto, encontramos uma linha já existente com essa palavra-chave e substituímos a 0
. Largamos tudo na nova linha e apenas mantemos a tabela atualizada.
s/^\([a-z]*\) *\([0-9]*\).*\n\([^_]*\)0_\(.*\)/__/
Outra correspondência, incluindo uma nova linha de linha 0
, para sabermos que não encontramos a palavra-chave na tabela (caso contrário, a linha nova teria sido removida antes. Dessa vez, adicionamos uma nova linha ao final. composto da palavra-chave, da linha do modelo e do valor. E esse é o truque da linha do modelo: adicionamos uma coluna \n
a ela para cada novo arquivo, por isso, se removermos uma 0
, teremos 0
coluna para cada arquivo em que essa palavra-chave não existia.
$! {h;d;}
Se esta não foi a última linha, mova a tabela modificada de volta para o espaço de espera ( 0
) e comece de novo ( h
).
s/[^_]*_//
Para a última linha, isso remove a linha do modelo.
y/_/\n/
E isso substitui d
por nova linha. Além disso, você também pode substituir espaços por guias, se desejar.
Editar
Se a suposição estiver errada de que cada arquivo começa com a linha _
, precisamos de um método diferente para informar foo
quando um novo arquivo for iniciado, como adicionar uma linha extra para cada arquivo iniciar e transmitir tudo para sed
:
for file in file*; do
echo Start of $file
cat $file
done | sed '1{x;s/$/__/;x;}
/Start of/{G;s/_/ 0_/g;s/Start of \(.*\)\n\([^_]*\)_\([^_]*\) 0/_ /;x;d;}
G;l;s/^\([a-z]*\) *\([0-9]*\).*\n\(.*_\)\([^_]*\)0//
l;s/^\([a-z]*\) *\([0-9]*\).*\n\([^_]*\)0_\(.*\)/ 0__/
$! {h;d;}
s/[^_]*_//
y/_/\n/'
Esta versão também gera a linha principal da tabela para todos os nomes de arquivos como cabeçalhos de coluna.