Teste a pesquisa sed recursiva e substitua antes de executar

13

Existe alguma maneira de executar uma pesquisa recursiva experimental e substituir usando sedantes de executá-la? Eu só quero imprimir os resultados antes de fazer a pesquisa e substituir. Algo como ecoar os resultados de,

grep -rl term1 . |xargs sed -i -e 's/term1/term2/'
user251482
fonte
Faça uma cópia dos dados, execute seu comando, inspecione o resultado.
Kusalananda

Respostas:

10

Você pode executar sedsem -ie avançar pela saída comless

grep -rl --null term1 . | xargs -0 sed -e 's/term1/term2/' | less

Em seguida, execute sedcom -i.bakpara criar backups que você poderá diferenciar posteriormente

grep -rl --null term1 . | xargs -0 sed -i.bak -e 's/term1/term2/'
diff somefile.bak somefile
# verify changes were correct

Editar: conforme sugerido no comentário, use grep --null | xargs -0. Isso faz com que os nomes de arquivos sejam finalizados pelo byte nulo, o que torna seguro para nomes de arquivos com caracteres incomuns, como nova linha. Sim, \né um caractere válido em um nome de arquivo unix. Os únicos caracteres proibidos são barra /e o caractere nul\0

Grebneke
fonte
Interessante, tentei encontrar o significado de -i, mas não estava listado em man sed. Sua solução funcionou. Qual seria a melhor maneira, na sua opinião, de listar apenas as linhas, não o arquivo inteiro? Em vez de canalizar para menos, eu canalizei | grep term2, que meio que funcionou, mas também obtive algumas saídas com caracteres estranhos.
user251482
@ user251482 - "Apenas liste as linhas", como em "visualizando uma diferença entre o arquivo antigo e o novo"?
grebneke
1
@StephaneChazelas Sim, ou melhor ainda, grep -rl --nulljá que o OP não especificou o SO e -Zsignifica algo diferente no BSD / OSX (descompactar). --nullé o mesmo no GNU e no BSD
grebneke
1
@grebneke. Bom ponto, mas observe que o OP está usando a sintaxe sed GNU, para que possamos assumir que ele não usa BSDs. Note que grepé (um fork) do GNU grep no FreeBSD e NetBSD. No NetBSD, -Zainda significa --null(de acordo com a página de manual), mas eu concordo - null é mais portátil. Observe também que nem --null nem -Z funcionam no OpenBSD
Stéphane Chazelas
1
@grebneke, é sed -i '' -e s/.../no BSD sed(sem opções opcionais lá)
Stéphane Chazelas
5

Use sedcom em findvez degrep

Antes de tudo, eu empregaria, finde não grep, e isso por três boas razões:

  1. findpermite a seleção de arquivos mais precisa. Por exemplo, grep -r string *.txtproduzirá arquivos apenas no diretório atual; não aqueles em subdiretórios.
  2. findvem com a -execopção poderosa que elimina a necessidade de toda a --null … |xargs 0construção.
  3. As opções -readablee evitarão perder tempo em arquivos que não podem ser acessados.-writablefind

Teste de captura

Dito isto, greppresta-se a um primeiro teste para ver o que seria capturado:

$ find . -exec grep term1 {} \;

ou mais especificamente:

$ find . -type f -name '*.txt' -readable -writable -exec grep term1 {} \;

Funcionamento a seco

Agora, prossiga com uma sedcorrida a seco. A sedopção -né um sinônimo --quiete pno final da sedexpressão imprimirá o espaço do padrão atual.

$ find . -exec sed -n 's/term1/term2/gp' {} \;

ou mais especificamente:

$ find . -type f -name '*.txt' -readable -writable -exec sed -n 's/term1/term2/gp' {} \;

Execução

Se tudo estiver bem, emita o comando definitivo substituindo a sedopção -npor -i"in place" e removendo o pno final.

$ find . -exec sed -i 's/term1/term2/g' {} \;

ou mais especificamente:

$ find . -type f -name '*.txt' -readable -writable -exec sed -i 's/term1/term2/g' {} \;

Mais findexemplos

Mais findexemplos podem ser encontrados aqui .

Serge Stroobandt
fonte