Você pode fazer algo bruto com um pequeno script Perl que é instruído a executar substituições linha por linha ( -l -pe
) nos arquivos passados como argumentos ( -i
):
perl -i -l -pe '
if (/from/) { # is the source text present on this line?
printf STDERR ("%s: %s [y/N]? ", $ARGV, $_); # display a prompt
$r=<STDIN>; # read user response
if ($r =~ /^[Yy]/) { # if user entered Y:
s/from/to/g; # replace all occurences on this line
}' /path/to/files
As possíveis melhorias seriam colorir partes do prompt e dar suporte a coisas como "substituir todas as ocorrências no arquivo atual". Solicitar separadamente cada ocorrência em uma linha seria mais difícil.
Segunda parte, combinando os arquivos. se não houver muitos arquivos envolvidos e você estiver executando o zsh, poderá corresponder todos os arquivos no diretório atual e seus subdiretórios recursivamente:
perl -i -l -pe '…' **/*(.)
Se o seu shell for bash ≥4, você poderá executar perl … **/*
, mas isso produzirá mensagens de erro falsas porque o sed tentará (e falhará) executar nos diretórios. Se você quiser executar a substituição apenas em um conjunto de arquivos, como arquivos C, poderá restringir as correspondências (que funcionam no bash ≥4 ou zsh):
perl -i -l -pe '…' **/*.[hc]
Se você precisar de um controle mais preciso sobre os arquivos que você está substituindo, ou se seu shell não possui a construção de correspondência de diretório recursiva **
, ou se você tiver muitos arquivos e receber um erro de "linha de comando muito longa", use find
. Por exemplo, para executar uma substituição em todos os arquivos nomeados *.h
ou *.c
no diretório atual e em seus subdiretórios (em sistemas mais antigos, pode ser necessário usá-lo em \;
vez de +
no final da linha (o +
formulário é mais rápido, mas não está disponível em todos os lugares).
find . -type f -name '*.[hc]' -exec perl -i -l -pe '…' {} +
Dito isto, eu me ateria a um editor interativo se você precisar de interação. Gert mostrou uma maneira de fazer isso no Vim , embora exija a abertura de todos os arquivos pelos quais você deseja pesquisar, o que pode ser um problema se houver muito.
No Emacs, veja como você pode fazer isso:
- Reúna os nomes dos arquivos com
M-x find-name-dired
(especifique um diretório de nível superior) ou M-x find-dired
(especifique uma find
linha de comando arbitrária ).
- No buffer direcionado resultante , pressione
t
para marcar todos os arquivos e, em seguida, Q
( dired-do-query-replace-regexp
) para executar uma substituição solicitando os arquivos marcados.
s/from/to/g
com uma falha de formatação depois dele, em vez des/from/to/gc
enfatizar oc
que você tentou escrever (você não pode fazer isso com o Markdown, você pode fazê-lo com<code>
e<strong>
tags HTML).