Как найти файлы, содержащие две строки в разных строках

Реальный пример: у меня есть файл Python util.py , и я сменил одно из имени функции с foo на bar . Могут быть другие файлы, использующие foo как имя функции, и они неактуальны.

Я хочу обновить все файлы Python в проекте от foo до bar . Поэтому я хотел бы выполнить поиск файлов для импорта, таких как:

 import project.path.util 

или

 from project.path.util import foo 

и любые вызовы foo например, начиная с:

 foo( 

Решение должно быть устойчивым к пробелам. Я могу искать каждый из них с помощью grep но я не уверен в комбинированном поиске. Любые предложения будут оценены.

  • Исключение нескольких шаблонов с помощью одной команды grep
  • Почему команда grep игнорирует период в строке поиска?
  • Необходимые команды для grep Неизвестное количество строк перед поиском строки поиска в файлах
  • Странное поведение «ls -a | grep ^ \. "
  • Почему grep игнорирует двоичные файлы по умолчанию?
  • Удаление строк, содержащих указанную строку в разных файлах
  • Найти строку между пробелами
  • Добавить строку суффикса в конец каждой строки?
  • 3 Solutions collect form web for “Как найти файлы, содержащие две строки в разных строках”

    С инструментами 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' 

    Это работает, прося grep to

    1. искать рекурсивно ( -r )
    2. вывод имен совпадающих файлов ( -l )
    3. разделенных NUL вместо LF ( -Z )
    4. считая только файлы, заканчивающиеся на '.py' ( --include='*.py' )

    и попросить sed выполнить замену на месте ( -i ) во всех совпадающих файлах, если они есть ( xargs -r ).

    Это должно быть сделано.

    /g заменит все экземпляры foo на bar

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

    Если вы хотите ограничить изменение только файлами * .py:

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

    Если есть случаи foo, которые не должны быть заменены, вы можете ограничить до 4 случаев:

    • импортировать foo
    • из модуля import foo
    • def foo
    • foo (

    Но нет

    • damned_foo (
    • damnedfoo (
    • damned1foo (
    • проклятый-Foo (

    Тогда команда будет выглядеть так:

     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" \; 

    Предположим, что вы находитесь в каталоге, который хотите выполнить поиск (он также соответствует любому подкаталогу):

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

    Редактировать:

    Чтобы избежать совпадения функций, содержащих символы, например «damned_fools», мы можем улучшить его с помощью \ b для соответствия границам слов:

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

    Ссылка: https://stackoverflow.com/questions/1032023/sed-whole-word-search-and-replace

    Linux и Unix - лучшая ОС в мире.