Sim, sua compreensão na segunda parte do texto está correta.
Pode-se dizer que o sed
, como muitas outras ferramentas do Unix, age como um filtro . Um filtro recebe entrada, modifica e produz saída. Em muitos casos, o utilitário que está fazendo a filtragem pode nem mesmo estar ciente de que está lendo ou gravando um arquivo . Na verdade, ele pode ler ou gravar em outro utilitário de filtro diretamente. Isso é transparente para o próprio utilitário e algo que o shell é responsável pela configuração.
Ignorando o fato de que o seguinte está usando cat
desnecessariamente,
cat <file | sed 's/^\([^=]*\)=\(.*\)$/#= # old/' | tr -s ' ' >newfile
Nenhum dos utilitários acima está ciente da leitura de um arquivo ou da gravação em um arquivo. cat
lê seu fluxo de entrada padrão (que o shell organiza para conter os dados de file
), provavelmente uma linha por vez, e grava sua saída em seu fluxo de saída padrão (sem modificações).
sed
lê o fluxo de entrada padrão its , que o shell já conectou ao fluxo de saída de cat
, faz algumas modificações em cada linha de entrada e grava o resultado em sua fluxo de saída padrão (que está conectado a tr
).
tr
apenas grava na saída padrão também, mas o shell configura o redirecionamento de tal forma que a saída entre no arquivo newfile
.
Em cada etapa deste processo, cada utilitário provavelmente só armazenará o que é minimamente necessário dos dados que passam pelo pipeline (em buffers alocados na RAM). Isso significa que os resultados podem começar a ser gravados em newfile
(neste exemplo) antes que os dados no arquivo file
tenham sido lidos completamente.
Seu exemplo específico:
sed "s/\${domain}/${1}/g" "nginx_app" > "/etc/nginx/sites-available/${domain}.conf"
O que está acontecendo:
-
O shell analisa a linha de comando e encontra as variáveis e os redirecionamentos.
-
O arquivo
/etc/nginx/sites-available/${domain}.conf
(com$domain
expandido para o valor dessa variável) é truncado (ou esvaziado) se existir, ou criado como um arquivo vazio, se não existir. -
O utilitário
sed
é chamado com os operandoss/\${domain}/${1}/g
(onde$1
já foi expandido para seu valor, mas${domain}
não, já que o$
é escapado com\
) enginx_app
. O shell também conecta a saída padrão desed
ao arquivo para o qual você está redirecionando. -
Como
sed
tem dois operandos, ele assumirá que o segundo é um arquivo para leitura. Ele abre e lê linha por linha enquanto aplica os comandos de edição no primeiro operando. -
Qualquer saída vai para o arquivo para o qual você redireciona.
Como as pessoas estão mencionando sed -i
:
O sinal -i
to sed
faz com que sed
execute suas alterações no arquivo fornecido no lugar , ou seja, ele não gravará em sua saída padrão, mas o resultado de as alterações serão refletidas no mesmo arquivo usado para entrada.
Internamente, sed
faz isso gravando em um arquivo temporário que posteriormente substitui o arquivo original.
O -i
flag possui um argumento (opcional para o GNU sed
e algumas outras implementações do utilitário, obrigatório para outros):
sed -i .bak '...some sed script...' filename
Isso faz o backup do arquivo original com a string fornecida como novo sufixo de nome de arquivo.
Eu geralmente tento desencorajar as pessoas de usar -i
com sed
, por alguns motivos:
- É uma extensão não padrão para o padrão POSIX
sed
. - Ele se comporta de maneira diferente em diferentes Unices. Veja a pergunta Como posso alcançar a portabilidade? com sed -i (edição no local)?
- É perigoso usar ao testar as coisas ou ao desenvolver um script, pois ele pode destruir os dados se o script
sed
estiver com defeito.
Em vez disso, recomendo que alguém faça algo nas linhas de
sed '...some sed script...' file >file-new && mv file-new file
... e adicione somente a parte && mv
quando a parte sed
foi testada corretamente.
O && mv
significa "se o comando anterior foi finalizado com sucesso (sem erro), renomeie este arquivo".