Сценарий для того, чтобы изменить имена класса C++

Я переместил свои классы от глобального пространства имен в определенное пространство имен. Я также изменил имена классов. Я хочу преобразовать все свои исходные файлы, которые используют эти классы для нового формата. Я думал любой a bash сценарий с помощью a sed файл на Cygwin или выполнении сценария жемчуга. Я испытываю затруднения из-за bash сценарий.

Вот процесс, который я пытаюсь выполнить:

  1. Для каждого исходного файла, *.cpp и *.hpp, рекурсивно:
  2. Если файл содержит старое имя класса, то преобразуйте файл.
  3. Конец для.

Моя проблема в Bash сценарий обнаруживает, если файл содержит старое имя класса. Я думал о том grep оператор для каждого имени класса:

for f in `find . -iname \*.[ch]pp`;
do
  if [ grep "Field_Blob_Medium" $f -eq 0 || grep "Field_Boolean" ]; then
      sed -f conversion.sed $f
  fi
done

Проблема - то, что только одна команда может быть в Bash если оператор, с помощью этого синтаксиса:

if grep "Field_Unsigned_Short" $f;

таким образом, я не могу сделать логического ИЛИ greps.

Я мог выполнить вложенный цикл, но я не знаю как к break из a Bash для цикла:

OLD_CLASS_NAMES="Field_Blob_Medium Field_Boolean Field_Unsigned_Int"
for f in `find . -iname \*.[ch]pp`;
do
  for c_name in $OLD_CLASS_NAMES;
  do
     if grep $c_name $f then
        sed -f convert.sed $f # <-- Need to break out of inner loop after this execution.
     fi
  done
done

Таким образом, я ищу предложения о том, как обработать каждый исходный файл, который содержит старые имена классов, и преобразуйте их в новые. Cygwin Bash пример сценария предпочтен, хотя сценарий Perl также был бы приемлем. Кроме того, сценарий должен сделать резервную копию файла первоисточника перед выписыванием преобразованного содержания к new файл.

Я выполняю Cygwin на Windows XP и Windows Vista.

6
задан Thomas Matthews 22 February 2010 в 21:39
поделиться

3 ответа

MyClass myObj();

Эта функция анализируется как объявление функции, называется myObj, не принимает аргументов и возвращает объект MyClass. Я никогда не видел, чтобы составитель принимал это. С другой стороны MyClass * myPtr = new MyClass (); является приемлемым, может быть, вы запутались?

-121--1070116-

Я бы добавил все в одно слово. Если не сложить все вместе, я бы либо сократил его, либо использовал _ .

В долгосрочной перспективе все, что вы решите выбрать, должно быть непротиворечивым .

-121--4561275-

Не уклоняйтесь от Perl: это делает эту задачу легкой!

#! /usr/bin/perl -i.bak

use warnings;
use strict;

my $old = join "|" => qw(
  Field_Blob_Medium
  Field_Boolean
  Field_Unsigned_Int
);

chomp(@ARGV = `find . -iname \*.[ch]pp -print0 |
               xargs -0 grep -lE '($old)'`);

unless (@ARGV) {
  warn "$0: nothing to do!\n";
  exit 0;
}

while (<>) {
  s[Field_Blob_Medium]  [my::ns::MediumBlob]g ||
  s[Field_Boolean]      [my::ns::Bool]g       ||
  s[Field_Unsigned_Int] [my::ns::UInt]g;

  print;
}

Переключатель -i предназначен для контекстного редактирования. Он автоматически создает резервные копии и записывает преобразованные результаты в исходные расположения.

Установка @ ARGV приводит к тому, что программа вызывалась только теми файлами * .cpp и * .hpp , которые содержат старые имена классов. Переключатель -E на grep включает расширенные регулярные выражения, так что незаметные (, ) и | являются метасимволителями.

Если попаданий не было ( т. е. , если @ ARGV пуст), то делать нечего.

В противном случае, для каждой строки каждого файла, который имеет старые имена (механикой которого управляет Perl!), попробуйте переименовать Field _ Blob _ Medium в my:: ns:: Medium Blob и так далее. Обратите внимание, что эти попытки замены прекращаются после первого успеха, поэтому, если строка содержит два разных старых имени, одно будет заменено, а другое останется прежним.

Обычно оператор подстановки записывается s///, но можно использовать квадратные разделители, как описано выше. Я сделал это, чтобы оправдать новые имена.

Конечно, это резерв для вашей фактической замены.

Наконец, напечатайте возможно измененную строку, которая из-за -i записывает ее в обновленный исходный файл.

2
ответ дан 17 December 2019 в 18:15
поделиться

Это работает на моем linux. Она управляет различными вещами, на которые указывали другие :

#!/bin/bash
OLD_NAMES="(EField_Blob_Medium|Field_Boolean|Field_Unsigned_Int)"

find "$1" -name "*.hpp" -o -name "*.cpp" -print0 | \
   xargs -0 --replace grep -E "${OLD_NAMES}" {} && sed -i.save -f convert.sed {}

Что важно :

  • опция -print0 в find с -0 xargs управляет файлами с пробелами. Она использует ASCII символ 'null' в качестве разделителя. Опция -0 в xargs понимает символ 'null' как разделитель: вы правильно управляете именами файлов с пробелами.
  • опция --replace используется для замены строки '{}' на текущий обрабатываемый файл
  • опция -i в sed создает резервную копию файла с помощью .save
  • && работают как сокращение if. Вторая часть выражения работает, только если первая часть истинна

Надеюсь, это поможет, my2c

1
ответ дан 17 December 2019 в 18:15
поделиться

Вы можете использовать параметр регулярного выражения для grep, чтобы дать вам больше гибкости в поиске. В вашем примере:

if [ grep "Field_Blob_Medium" $f -eq 0 || grep "Field_Boolean" ];

может быть

if [ grep -E "(Field_Blob_Medium|Field_Boolean)" ... ];

Вы можете связать эти '|' вместе, сколько душе угодно.

Кроме того, вы можете объединить свои находки в greps

find . -name "*.hpp" or -name "*.cpp" | xargs grep -E ...

... на случай, если вы захотите упростить этот цикл.

0
ответ дан 17 December 2019 в 18:15
поделиться
Другие вопросы по тегам:

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