trabalhando - using sed shell




Comando sed localizar e substituir no arquivo e sobrescrever o arquivo não funciona, ele esvazia o arquivo (9)

Com todo o respeito às respostas corretas acima, é sempre uma boa ideia executar scripts "dry run" como esse, para que você não corrompa seu arquivo e tenha que começar do zero.

Basta fazer com que seu script transmita a saída para a linha de comando em vez de gravá-la no arquivo, por exemplo, assim:

sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html

OU

less index.html | sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g 

Dessa forma, você pode ver e verificar a saída do comando sem ter seu arquivo truncado.

Eu gostaria de executar um localizar e substituir em um arquivo HTML através da linha de comando.

Meu comando é algo como isto:

sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html > index.html

Quando eu corro isso e olho para o arquivo depois, ele está vazio. Ele excluiu o conteúdo do meu arquivo.

Quando eu executo isso depois de restaurar o arquivo novamente:

sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html

O stdout é o conteúdo do arquivo e o localizar e substituir foi executado.

Por que isso está acontecendo?


E a resposta ed :

printf "%s\n" '1,$s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' w q | ed index.html

Para reiterar o que o codaddict respondeu , o shell lida com o redirecionamento primeiro , apagando o arquivo "input.html" e, em seguida, o shell chama o comando "sed" passando um arquivo agora vazio.


O problema com o comando

sed 'code' file > file

é que o file é truncado pelo shell antes de o sed realmente processá-lo. Como resultado, você obtém um arquivo vazio.

A maneira mais fácil de fazer isso é usar -i para editar no lugar, como outras respostas sugeriram. No entanto, isso nem sempre é o que você deseja. -i criará um arquivo temporário que será usado para substituir o arquivo original. Isso é problemático se o arquivo original for um link (o link será substituído por um arquivo normal). Se você precisa preservar os links, você pode usar uma variável temporária para armazenar a saída do sed antes de escrevê-lo de volta para o arquivo, assim:

tmp=$(sed 'code' file); echo -n "$tmp" > file

Melhor ainda, use printf vez de echo pois é provável que o echo processe \\ como \ em alguns shells (por exemplo, traço):

tmp=$(sed 'code' file); printf "%s" "$tmp" > file

Para alterar vários arquivos (e salvar um backup de cada como * .bak):

perl -p -i -e "s/\|/x/g" *  

vai levar todos os arquivos no diretório e substituir | com x isso é chamado de "torta Perl" (fácil como uma torta)


Um padrão alternativo e útil é:

sed -e 'script script' index.html > index.html.tmp && mv index.html.tmp index.html

Isso tem praticamente o mesmo efeito, sem usar a opção -i , e adicionalmente significa que, se o script sed falhar por algum motivo, o arquivo de entrada não será destruído. Além disso, se a edição for bem-sucedida, não haverá nenhum arquivo de backup por aí. Esse tipo de idioma pode ser útil em Makefiles.

Um monte de seds tem a opção -i , mas nem todos eles; o posix sed é aquele que não o faz. Se você está apontando para portabilidade, portanto, é melhor evitar.


Você deve tentar usar a opção -i para edição no local.


use a opção -i do sed, por exemplo

sed -i bak -e s/STRING_TO_REPLACE/REPLACE_WITH/g index.html

Atenção: este é um método perigoso! Abusa os buffers de i / o no linux e com opções específicas de buffering consegue trabalhar em arquivos pequenos. É uma curiosidade interessante. Mas não use isso para uma situação real!

Além da opção -i do sed você pode usar o utilitário tee .

Do man :

tee - ler a partir da entrada padrão e gravar na saída e nos arquivos padrão

Então, a solução seria:

sed s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html | tee | tee index.html

- aqui o tee é repetido para se certificar de que o pipeline está em buffer. Em seguida, todos os comandos no pipeline são bloqueados até que recebam alguma entrada para trabalhar. Cada comando no pipeline começa quando os comandos upstream escrevem 1 buffer de bytes (o tamanho é definido em somewhere ) para a entrada do comando. Portanto, o último comando tee index.html , que abre o arquivo para gravação e, portanto, o esvazia, é executado após o término do pipeline upstream e a saída está no buffer dentro do pipeline.

O mais provável é que o seguinte não funcione:

sed s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html | tee index.html

- Ele executará os dois comandos do pipeline ao mesmo tempo sem nenhum bloqueio. (Sem bloquear o pipeline deve passar os bytes linha por linha em vez de buffer por buffer. O mesmo que quando você executa cat | sed s/bar/GGG/ . Sem bloqueá-lo é mais interativo e geralmente pipelines de apenas 2 comandos são executados sem buffering e bloqueio Pipelines mais longas são armazenadas em buffer.) O tee index.html abrirá o arquivo para gravação e será esvaziado. No entanto, se você ativar o armazenamento em buffer sempre, a segunda versão funcionará também.


sed -i.bak "s#https.*\.com#$pub_url#g" MyHTMLFile.html

Se você tiver um link para ser adicionado, tente isso. Pesquise o URL como acima (começando com https e terminando com.com aqui) e substitua-o por uma string de URL. Eu usei uma variável $pub_url aqui. s aqui significa search e g significa substituição global.

Funciona !





sed