Поиск и замена сотни строк в десятках тысяч файлов?

Я изучаю изменение имени файла сотен файлов в (C/C++) проект, что я продолжаю работать. Проблемой является наше программное обеспечение, имеет десятки тысяч файлов, что включая (т.е. #include) эти сотни файлов, которые будут изменены. Это похоже на кошмар обслуживания. Если я сделаю это, то я буду застревать в Ультраредактировании в течение многих недель, прокручивая сотни regex's вручную как так:

^\#include.*["<\\/]stupid_name.*$

с

#include <dir/new_name.h>

Такая тяжелая работа была бы хуже, чем очищение сотен картофеля в затонувшей подводной лодке в Антарктике с ложкой. Я думаю, что это было бы идеально для помещения вводов и выводов в таблицу как так:

stupid_name.h <-> <dir/new_name.h>
stupid_nameb.h <-> <dir/new_nameb.h>
stupid_namec.h <-> <dir/new_namec.h>

и подайте это в механизм регулярного выражения / инструмент / приложение / и т.д...

Мой Окончательный Вопрос: существует ли инструмент, который сделает это?

Вопрос о премии: действительно ли это является многопоточным?

Я посмотрел, довольно многие ищут и заменяют темы здесь на этом веб-сайте и нашли много стандартных запросов, которые спросили вариант следующего вопроса:

стандартный вопрос: Замените один термин в файлах N.

в противоположность:

мой вопрос: Замените условия N в файлах N.

Заранее спасибо за любые ответы.

5
задан C Johnson 21 April 2010 в 02:41
поделиться

7 ответов

Как говорит Марк Уилкинс, это работоспособный план с любым удобным инструментом для создания сценариев с регулярными выражениями, который вы предпочитаете, но я бы предложил пару дополнительных моментов:

  1. Используйте два сценария: один для преобразования вашего списка в регулярные выражения, а другой для их применения. Попытка выполнить обе задачи в одном скрипте вызывает проблемы.
  2. Не забудьте изменить директивы #include и одновременно переименовать файлы заголовков.
  3. Если вы знаете, как изменить одну вещь в N файлах, тогда, черт возьми, вы можете просто перебрать K вещей, которые хотите изменить. Это не самый эффективный способ с точки зрения процессорного времени, но это не узкое место.
  4. Этот подход будет работать теоретически, но если он сработает на практике с первого раза, ваша база кода станет чище. чем что-либо (такого размера), которое я когда-либо видел. Почти наверняка будут небольшие сюрпризы: жестко запрограммированный путь, который не соответствует регулярному выражению, плохое имя, которое конфликтует с хорошим именем, какой-то другой сбой, о котором никто бы не подумал. Я предлагаю начать с малого, с одной или двух пар имен, компилировать после каждой замены и отступить в случае проблем. Если вы все сделаете правильно, вы можете настроить его на работу в течение ночи, а утром у вас будет уже почти готовая рабочая база кода и список имен, которые вызвали проблемы и требуют внимания человека.
1
ответ дан 14 December 2019 в 19:06
поделиться

PowerGREP может это сделать. Он может искать несколько строк поиска (буквальный текст или регулярные выражения) в любой комбинации файлов и является многопоточным (начиная с PowerGREP 4, текущей версии).

альтернативный текст http://img682.imageshack.us/img682/5172/screen006c.png

Вы можете сохранить результаты поиска для последующего повторного использования.

0
ответ дан 14 December 2019 в 19:06
поделиться

Я думаю, что ваш Идея размещения старых / новых имен в одном месте - хорошая.Это, безусловно, уменьшит сложность поддержания и проверки изменений. Кажется, что это очевидный ответ, но я думаю, что использование любого из популярных языков сценариев, таких как ruby, python, perl и т. Д., Сделает эту задачу довольно простой. Сценарий может прочитать файл, содержащий старую / новую информацию о замене, построить из нее соответствующие регулярные выражения, а затем обработать файлы, которые нуждаются в замене.

Сценарий можно было бы написать как многопоточную утилиту, хотя не похоже, что в такой ситуации будет много пользы. Если я понимаю вопрос, это должно быть в основном одноразовое использование, поэтому высокая производительность не кажется главным приоритетом.

1
ответ дан 14 December 2019 в 19:06
поделиться

Создайте серию однострочных файлов perl для редактирования файлов на месте, например:

perl -i.bak -p -e 's/stupid_old_name/cool_new_name/' *.c

Это дает дополнительный бонус в виде сохранения оригиналов любых измененных файлов с расширением .bak.

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

На этом веб-сайте очень хорошо объясняется редактирование на месте с помощью perl: http://www.rice.edu/web/perl-edit.html

PS - Поскольку я достаточно хорошо знаю Perl ну, я бы просто написал таблицу was / is в «реальном» perl-скрипте и использовал бы ее для открытия и анализа всех файлов.

1
ответ дан 14 December 2019 в 19:06
поделиться

Я бы использовал awk, инструмент командной строки, похожий на sed.

mv file.x file.x.bak;
awk '{
  gsub( "#include \"bad_one.h\"" , "#include \"good_one.h\"" );
  gsub( "#include \"bad_two.h\"" , "#include \"good_two.h\"" );
}' file.x.bak > file.x;

Когда вы окажетесь у терминала, используйте man awk , чтобы увидеть более подробную информацию.

2
ответ дан 14 December 2019 в 19:06
поделиться

Сработает ли этот (Вингреп)?

0
ответ дан 14 December 2019 в 19:06
поделиться

в * nix (или GNU win32), вы можете использовать GNU find и sed вместе ... например,

find /path -type f -name "*.c" -exec  sed -i.bak 's/^\#include.*["<\\/]stupid_name.*$/#include <dir\/new_name.h>/' "{}" +;

объяснение,

команда find начинает поиск файлов ( -тип f ), начиная с / path . -name "* .c" ищет все файлы .c , затем для каждого найденного выполняет sed , чтобы заменить строку на новую. -i.bak просит sed сохранить исходный файл в качестве резервной копии перед редактированием на месте. "{}" означает файл, переданный в sed

0
ответ дан 14 December 2019 в 19:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: