2010-02-22 11 views
6

Przeniosłem moje klasy z globalnej przestrzeni nazw do określonej przestrzeni nazw. Zmieniłem również nazwy klas. Chcę przekonwertować wszystkie moje pliki źródłowe, które używają tych klas, do nowego formatu. Myślałem o skrypcie bash przy użyciu pliku sed na Cygwin lub wykonywaniu skryptu perl. Mam problem ze skryptem bash.Skrypt do zmiany nazw klasy C++

Oto proces próbuję wykonać:

  1. dla każdego pliku źródłowego, * .cpp i * .hpp, rekurencyjnie:
  2. Jeśli plik zawiera starą klasę nazwę, a następnie przekonwertuj plik.
  3. Koniec.

Mój problem w wykrywaniu wykrywa, czy plik zawiera starą nazwę klasy. Myślałam o jednym grep rachunku dla każdej nazwy klasy:

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 

Problem jest, że tylko jedno polecenie może być w Bash if, używając następującej składni:

if grep "Field_Unsigned_Short" $f; 

więc nie mogę zrobić logiczne OR z grep.

mogłem wykonać zagnieżdżonych pętli, ale nie wiem jak break się z Bash pętli for:

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 

więc szukam dla sugestii, w jaki sposób przetwarzać każdy plik źródłowy, który zawiera stare nazwy klas i przekonwertuj je na nowe. Przykład skryptu Cygwin Bash jest preferowany, chociaż skrypt Perla byłby również akceptowalny. Ponadto skrypt powinien wykonać kopię zapasową oryginalnego pliku źródłowego przed zapisaniem skonwertowanej zawartości na plik new.

Używam Cygwin na Windows XP i Windows Vista.

+1

cant Po prostu używasz grep z wieloma regexp? grep -e "Field_Blob_Medium" -e "Field_Boolean" -e "Field_Unsigned_Int" ... ? – lollinus

+1

aby wykonać kopię zapasową każdego przetworzonego pliku: sed -i.bak -f convert.sed $ f – lollinus

+0

'break' zrywa z pętli' for' i możesz zrobić 'if prog || prog || prog' dla logicznego OR (ale w tym przypadku zmiana regex jest lepsza). 'dla' z' find' jest zwykle złym pomysłem, ponieważ kończy się niepowodzeniem, gdy nazwy plików mają spacje. Lepiej jest "wpadać" na 'while'. –

Odpowiedz

2

Nie uciekać od Perl: to sprawia, że ​​ten rodzaj zadania proste!

#! /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; 
} 

Przełącznik -i służy do edycji w miejscu. Automatycznie tworzy kopie zapasowe i zapisuje przekształcone wyniki w oryginalnych lokalizacjach.

Ustawienie @ARGV powoduje, że ustawienie @ARGV powoduje, że program był wywoływany tylko z plikami *.cpp i *.hpp zawierającymi stare nazwy klas. Przełącznik -E na grep umożliwia rozszerzone wyrażenia regularne, dzięki czemu nieodwracalne są znaki metaznaków.

Jeśli nie było trafień (, tj., jeśli @ARGV jest pusta), to nie ma nic do zrobienia.

W przeciwnym razie, dla każdego wiersza każdego pliku, który ma stare nazwy (których mechanik obsługuje Perl!), Spróbuj zmienić nazwę na Field_Blob_Medium na my::ns::MediumBlob i tak dalej. Zauważ, że te próby zastępowania kończą się po pierwszym sukcesie, więc jeśli linia zawiera dwie różne stare nazwy, jedna zostanie zastąpiona, a druga pozostanie taka sama.

Zwykle operator zastępczy jest pisany s///, ale można użyć ograniczników nawiasów, jak powyżej. Zrobiłem to, by usprawiedliwić nowe nazwiska.

Oczywiście jest to stand-in dla rzeczywistej zamiany.

Wreszcie, print z ewentualnie zmodyfikowaną linią, która z powodu -i zapisuje ją do zaktualizowanego pliku źródłowego.

0

Można użyć opcji wyodrębnienia dla grep, aby zapewnić większą elastyczność wyszukiwania. Na swoim przykładzie:

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

może być

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

Mogłabyś ciąg razem te '|' s do syta.

Plus można połączyć swoje znaleziska do swoich greps

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

... w przypadku, gdy chcesz, aby uprościć tam tej pętli.

1

Ta praca na moim Linuxie.Zarządza on różne rzeczy wskazywanego przez innych:

#!/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 {} 

Co jest ważne:

  • -print0 możliwość dowiedzieć się o xargs -0 zarządza plików ze spacjami. Używa znaku ASCII "null" jako separatora. Opcja -0 xargs rozumie znak "null" jako separator: poprawnie zarządzasz nazwami plików spacjami.
  • opcja --replace jest stosowany do zastąpienia „{}” łańcuch obecnym przetworzony
  • z opcji -I SED kopię zapasową pliku z .save
  • & & pracy jako skrót z if. Druga część wypowiedzi działa tylko wtedy, gdy pierwsza część jest prawdą

nadzieję, że helsp, my2c

Powiązane problemy