Você já precisou realizar uma operação de localização e substituição que abrange vários arquivos em seu projeto? Fazer essa operação arquivo por arquivo pode ser entediante. Buscar uma resposta para este problema pode ser frustrante devido ao envolvimento de muitas ferramentas Unix diferentes, cada uma com suas próprias opções. Alguns desses sinalizadores são incompatíveis entre o Linux e o OS X, portanto, ele pode rapidamente evoluir para conectar uma solução e seguir em frente quando ela falhar.
Algumas notas sobre meu ambiente:
- Editor de texto Vim
- Git source control
- Ferramenta de pesquisa de reconhecimento
A solução
Aqui está uma solução à prova de balas de localizar e substituir usando a mesma ferramenta de pesquisa que eu uso dentro do Vim – o maravilhoso Ack ( http://beyondgrep.com/ )
ack <search term> -l --print0 | xargs -0 sed -i '' 's/<search term>/<replacement term>/g'
- O ack recebe um termo de pesquisa e, com o
-l
sinalizador, exibe apenas nomes de arquivos --print0
separa os nomes de arquivos com um byte nulo em vez de uma nova linha. Isso é bom para nomes de arquivos que contenham espaços (não programadores!)- Pegamos a lista resultante e canalizamos para
xargs
que iterará em cada lista e aplicamos o seguinte comando. Observe o-0
sinalizador para que ele saiba procurar o caractere de byte nulo - Em seguida vem
sed
. A implementação do OS X requer uma extensão seguindo a-i
bandeira para a funcionalidade de edição no local. Passamos uma string vazia (''
) para dizer a ele para não usar uma extensão - Finalmente, fazemos nossa função sed s / expressão regular / substituição / sinalizadores.
s
é para o substituto, e no final significa fazer as substituições para todas as partidas/g
Por que não ViM?
O Vim não oferece suporte a nenhuma solução global rápida de localização e substituição. A maioria parece envolver o preenchimento do argbuffer e, a seguir, iterar essas coleções ou instalar plug-ins. Eu também estava tendo problemas com prompts para salvar minhas alterações antes de alterar os buffers, eliminando a operação de loop. ATUALIZAÇÃO As possíveis soluções para deixar buffers modificados estão documentadas aqui 1 Achei que seria melhor fazer isso fora do ViM, selecionando a partir de uma gama completa de ferramentas Unix.
Por que não encontrar ou fazer grep?
Sou a favor do ack porque conhece o contexto do código-fonte. Ele sabe pular arquivos de log e tmp, bem como metadados de controle de versão. A operação resultante não é apenas muito mais rápida, mas você pode ter certeza de que não está mexendo com nenhuma configuração estranha em lugares que não deveriam ser tocados.
Por que não aplicar o sed a todos os arquivos?
Git é sensível a espaços em branco. Sed irá tocar no arquivo independentemente de as alterações terem sido feitas ou não. Isso significa que você pode acabar com uma nova linha no final do arquivo, que agora deve ser escalonada ou revertida. Embora git diff
tenha um sinalizador para ignorar os espaços em branco, não o faz. prepara os arquivos, então a solução envolveria canalizar a saída de git diff para git add. Isso teria sido bobo, pois podemos omitir que esses arquivos sejam tocados para começar a usar .git add
git add
ack