substitui com SED recursivamente

3

É possível substituir um exemplo recursivamente em multi-diretório com grep e sed assim?

grep -e "http://localhost:4000" -r ~/dev_web/_site  | sed -e 's/http:\/\/localhost:4000/https:\/\/another_site.com/g'

Quando faço isso, meu terminal me mostra que está pronto, mas quando eu faço novamente um grep:

grep -e "https://another_site.com" -r ~/dev_web/_site

ele mostra apenas 4 arquivos alterados ...

E se eu fizer isso:

 grep -e "http://localhost:4000" -r ~/dev_web/_site/

o exemplo http: localhost: 4000 ainda está aqui

    
por ordinatous 04.07.2018 / 14:16

3 respostas

3

Seu pipeline não altera arquivos. Ele extrai linhas que correspondem à expressão regular usando grep e, em seguida, altera esses dados, mas não tenta fazer alterações em nenhum arquivo.

Em vez disso, assumindo o GNU sed :

find ~/dev_web/_site -type f \
    -exec grep -qF 'http://localhost:4000' {} ';' \
    -exec sed -i 's#http://localhost:4000#https://another.site#g' {} +

Isso localizaria todos os arquivos regulares no diretório ~/dev_web/_site . Para cada arquivo, grep primeiro testa se o arquivo contém a string dada. Em caso afirmativo, o GNU sed é invocado para fazer uma substituição no local.

A etapa grep poderia ser omitida, mas o GNU sed atualizaria o registro de data e hora da modificação nos arquivos todos sem ela.

Você pode querer apenas olhar em um subconjunto dos arquivos nos diretórios abaixo de ~/dev_web/_site . Se esse for o caso, restrinja a pesquisa com algo como -name '*.js' (ou qualquer padrão de nome que você deseja corresponder) logo após -type f .

Adicionar -print antes de -exec sed ... imprimir os nomes de caminho dos arquivos que find daria a sed .

Relacionados:

por 04.07.2018 / 14:30
1

sua sessão sed trabalhou na saída do grep, não no arquivo atual.

use grep para listar o arquivo (*)

grep -e "http://localhost:4000" -r ~/dev_web/_site -l 

use xargs e sed -i para editar no lugar

xargs sed -i -e 's;http://localhost:4000;https://another_site.com;g'

(em uma nota lateral você pode alterar o delimitador no sed)

Agora todos juntos

grep -e "http://localhost:4000" -r ~/dev_web/_site -l |
xargs sed -i -e 's;http://localhost:4000;https://another_site.com;g'

Isso pode ser feito com uma única linha, note que o símbolo de pipe ( | ) pode ser usado com uma continuação de linha.

(*) Presumo que o arquivo não tenha espaço, nova linha e outros caracteres engraçados em seus nomes.

    
por 04.07.2018 / 14:27
1

Suas primeiras linhas de extração grep de arquivos, não arquivos list .
Para obter uma lista de arquivos correspondidos, use a opção -l para grep:

$ grep -rl "htt...."  ~/dir

Para executar a modificação dos arquivos com sed, forneça a lista para sed (inverter a ordem):

$ sed -e 's#http://localhost:4000#https://another_site.com#g' \
$(grep -rle "http://localhost:4000" ~/dev_web/_site)

Isso pressupõe nomes de arquivos "limpos": sem espaços ou novas linhas.

Uma opção mais robusta é usar o find:

fromname='http://localhost:4000
toname='https://another_site.com'
searchdir=~/dev_web/_site
find "$searchdir" -type f \
    -exec grep -qF "$fromname" {} ';' \
    -exec sed -i 's#'"$fromname"'#'"$toname"'#g' {} +
    
por 04.07.2018 / 18:59