Minha pergunta está relacionada à sed
solução específica dada nesta resposta para esta questão de grepping reverso . A solução sed
/ grep
que não consigo decifrar é a seguinte:
sed '1!G;h;$!d' file
Alguém pode decifrar este comando?
Sei pelo VI (M) conhecimento que G denota a última linha do arquivo e que, em caso de estrondo (!) Seguido de um endereço, funciona um pouco assim, grep -v
ou seja, para dizer que não corresponderá a essa linha. Mas como um todo, o script sed inline acima está além de mim.
sed
receita complicada é uma maneira extremamente ineficiente (complexidade O (n ^ 2/2)) de inverter linhas em um arquivo. Seria proibitivamente lento para arquivos com um grande número de linhas. Para uma alternativa de reversão de ordem de linha muito mais eficiente, consulte ostac
coreutils do GNU.Respostas:
Isso inverte o arquivo linha por linha.
Primeiro,
sed
possui um espaço de espera e um espaço de padrão . Temos que distinguir entre eles antes de nos concentrarmos nesse comando específico.Quando
sed
lê uma nova linha, ela é carregada no espaço do padrão. Portanto, esse espaço é substituído toda vez que uma nova linha é processada. Por outro lado, o espaço de espera é consistente em todo o processamento e os valores podem ser armazenados lá para uso posterior.Para o comando:
Existem 3 comandos nesta declaração:
1!G
,h
e$!d
1!G
significa que oG
comando é executado em todas as linhas, exceto na primeira (a!
nega a1
).G
significa acrescentar o que está no espaço de espera no espaço do padrão.h
aplica-se a todas as linhas. Ele copia o espaço do padrão para o espaço de espera (e o substitui).$!d
aplica-se a todas as linhas, exceto a última ($
representa a última linha,!
nega-a).d
é o comando para excluir a linha (espaço do padrão).sed
executa oh
comando. A primeira linha é copiada no espaço de espera. Em seguida, é excluído, pois corresponde à$!
condição.sed
continua com a segunda linha.1!
(não é a primeira linha) e, portanto, o espaço de espera (que tem a primeira linha) é anexado ao espaço do padrão (que tem a segunda linha). Depois disso, no espaço do padrão, agora existe a segunda linha seguida pela primeira, delimitada por uma nova linha. Agora, oh
comando se aplica (como em todas as linhas); tudo o que está no espaço do padrão é copiado para o espaço de espera. A terceira instrução ($!d
) se aplica: A linha é excluída do espaço do padrão.$
), quase toda a Etapa 2 está concluída, mas não a parte de exclusão (d
).sed
, quando chamado sem-n
, imprime o espaço do padrão automaticamente no final do processamento para cada linha de entrada. Portanto, quando não excluído, o espaço do padrão é impresso. Ele contém agora todas as linhas na ordem inversa .fonte
h
comando copia o espaço do padrão para o espaço de espera, que persiste até osed
fim. Após o final do script, tudo é limpo, porque o binário saiu.sed
apenas um espaço de espera. É como uma variável que pode conter algo.-n
, temos que excluir todas as linhas, exceto a última. Na última linha, sed acrescenta tudo, desde o espaço de espera até o espaço do padrão. E como od
comando não será executado, a linha é impressa (esta linha contém agora todo o arquivo invertido).h
comando na última linha é uma espécie de não operação ”. (Com ênfase adicional e parafraseada ligeiramente). Ele tem razão; quandosed
está processando a última linha de entrada ,G
lê o espaço de espera (para anexá-lo ao espaço de padrão) eh
copia o espaço de padrão para o espaço de espera, que nunca é referenciado novamente . Poderíamos muito bem dizersed 'G;$!h;$!d'
oused 'G;$!{h;d}'
. (2) Poderíamos evitar usard
dizendosed -n 'G;h;$p'
.