Dado um arquivo, quero fazer uma lista de todos os bytes que ele contém em formato octal, cada byte em sua própria linha.
Por que isso funciona:
#!/bin/sh --
newline='
'
od -v -A n -t o1 -- /tmp/file | \
sed -e "s/ /\\${newline}/g" | \
sed -e '/^$/d'
e não isso:
#!/bin/sh --
newline='
'
od -v -A n -t o1 -- /tmp/file | \
sed -e "s/ /\\${newline}/g" -e '/^$/d'
Por que eu tenho que ligar para o sed duas vezes separadas para fazer o trabalho?
Para referência, a saída de od
, sem processamento adicional, pode ser algo como o seguinte:
047 124 167 141 163 040 142 162 151 154 154 151 147 054 040 141
156 144 040 164 150 145 040 163 154 151 164 150 171 040 164 157
166 145 163 012 011 104 151 144 040 147 171 162 145 040 141 156
144 040 147 151 155 142 154 145 040 151 156 040 164 150 145 040
167 141 142 145 072 012 101 154 154 040 155 151 155 163 171 040
167 145 162 145 040 164 150 145 040 142 157 162 157 147 157 166
145 163 054 012 011 101 156 144 040 164 150 145 040 155 157 155
145 040 162 141 164 150 163 040 157 165 164 147 162 141 142 145
056 012
Cada
sed
expressão atua em todo o espaço do padrão. No início de um ciclo, uma linha é lida no espaço padrão e, em seguida,sed
aplica-se cada expressão fornecida a esses dados.Na segunda variação do seu código, você insere novas linhas no espaço do padrão com a substituição. A segunda expressão,
/^$/d
, ainda atuará no espaço padrão como um todo, não em cada linha individual no espaço padrão, o que significa que o padrão não corresponderá (já que o buffer não está vazio) e o espaço padrão não ser excluído. Mudar/^$/d
paras/\n\{2,\}//g
excluiria qualquer execução de dois ou mais caracteres de nova linha consecutivos (estes criariam linhas vazias na saída), o que teria funcionado.Isso contrasta com a primeira variação do código, onde o segundo
sed
lê a saída do primeirosed
. Nesse caso, o segundosed
lerá cada linha gerada individualmente e excluirá as que estiverem vazias.Resumindo: Adicionar novas linhas no espaço do padrão não fará com que
sed
reconsidere cada linha gerada como entrada individual para as expressões restantes.Uma solução alternativa:
A primeira
sed
expressão,s/ \{2,\}//g
, elimina qualquer execução de dois ou mais espaços consecutivos e, em seguida, a segunda expressão converte os espaços restantes em novas linhas (\n
é permitido com oy
comando, mesmo em POSIXsed
).Ou você pode excluir todos os espaços adjacentes antes de converter todos os espaços restantes em novas linhas:
(Observe que apenas a última linha de saída
od
pode ter espaços à direita, e é por isso que uso$
como endereço para a segunda expressão.)Ou, pode ser mais simples com
awk
:Isso porque as linhas vazias existem apenas no arquivo de saída, após as substituições terem sido feitas. Por que não
?