Como encontrar arquivos contendo duas cadeias de caracteres em linhas diferentes

6

Um exemplo real é: Eu tenho um arquivo Python util.py e mudei um dos nomes de função de foo para bar . Pode haver outros arquivos usando foo como nome da função e eles são irrelevantes.

Eu quero atualizar todos os arquivos Python no projeto de foo para bar . Então eu gostaria de fazer uma pesquisa em arquivos para importações como:

import project.path.util

ou

from project.path.util import foo

e todas as chamadas para foo , como uma que começa com:

foo(

A solução tem que ser tolerante a espaço em branco. Eu posso pesquisar cada um deles usando grep , mas não tenho certeza sobre a pesquisa combinada. Qualquer sugestão será apreciada.

    
por Xiaoge Su 19.04.2014 / 02:32

3 respostas

5

Com ferramentas GNU:

grep -rlZ --include='*.py' -e 'import project.path.util' \
                           -e 'from project.path.util import.*\bfoo\b' . |
  xargs -r0 sed -i 's/\bfoo\b/bar/g'

Isso funciona perguntando grep a

  1. pesquisar recursivamente ( -r )
  2. exibindo nomes de arquivos correspondentes ( -l )
  3. separados por NUL em vez de LF ( -Z )
  4. considerando apenas os arquivos que terminam em '.py' ( --include='*.py' )

e pedindo a sed para realizar a substituição no local ( -i ) em todos os arquivos correspondentes, se houver algum ( xargs -r ).

    
por 19.04.2014 / 08:40
0

Isso deve ser feito.

/g substituirá todas as instâncias de foo por bar

find <Project root dir> -type f -exec sed -i "{}" -e 's/foo/bar/g' \;

Se você quiser restringir a alteração apenas aos arquivos * .py:

find <Project root dir> -type f -name "*.py" -exec sed -i "{}" -e 's/foo/bar/g' \;

Se houver instâncias de foo que não devem ser substituídas, você poderá restringir a quatro casos:

  • import foo
  • da importação do módulo foo
  • def foo
  • foo (

Mas não

  • damned_foo (
  • damnedfoo (
  • damned1foo (
  • maldito-foo (

Então o comando ficaria assim:

foo="foo";bar="bar";find <Project root dir>  -type f -exec sed -i "{}" \
-r -e "s/[^a-zA-Z0-9_\-]$foo\(/$bar\(/g" -e "s/def $foo/def $bar/g" \
-e "s/import $foo/import $bar/g" \;
    
por 19.04.2014 / 03:55
0

Suponha que você esteja no diretório do qual deseja pesquisar (ele também corresponde a qualquer subdiretório):

 for i in 'find . -type f -name '*.py' -exec grep -lr 'foo' {} +'; do sed -i 's/foo/bar/' $i; done

Editar:

Para evitar funções correspondentes que contenham os caracteres, como "damned_fools", podemos aprimorá-lo com \ b para corresponder aos limites das palavras:

for i in 'find . -type f -name '*.py' -exec grep -lr 'foo' {} +'; do sed -i 's/\bfoo\b/bar/' $i; done

Referência: link

    
por 19.04.2014 / 03:45

Tags