2010-02-22 11 views
6

Ho spostato le mie classi da uno spazio dei nomi globale in uno spazio dei nomi specifico. Ho anche cambiato i nomi delle classi. Voglio convertire tutti i miei file sorgente che utilizzano queste classi nel nuovo formato. Stavo pensando allo script bash usando un file sed su Cygwin o eseguendo uno script perl. Sto avendo problemi con lo script bash.Script per modificare i nomi delle classi C++

Ecco il processo che sto cercando di realizzare:

  1. Per ogni file sorgente, * cpp e * .hpp, in modo ricorsivo:
  2. Se il file contiene un vecchio nome della classe , poi convertire il file.
  3. Fine per.

Il mio problema nello script Bash sta rilevando se il file contiene un nome di classe precedente. Stavo pensando di una grep dichiarazione per ogni nome di classe:

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 

Un problema è che solo un comando può essere in Bash if, utilizzando questa sintassi:

if grep "Field_Unsigned_Short" $f; 

quindi non posso fare un OR logico di grep s.

ho potuto eseguire un ciclo nidificato, ma non so come break fuori da un ciclo for 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 

Quindi sono alla ricerca di suggerimenti su come elaborare ogni file di origine che contiene vecchi nomi di classe e convertirli in nuovi. È preferibile un esempio di script Cygwin Bash, sebbene anche uno script Perl sia accettabile. Inoltre, lo script deve eseguire una copia di backup del file di origine originale prima di scrivere i contenuti convertiti nel file new.

Sono in esecuzione Cygwin su Windows XP e Windows Vista.

+1

non puoi usare solo grep con regexp multipli? grep -e "Field_Blob_Medium" -e "Field_Boolean" -e "Field_Unsigned_Int" ... ? – lollinus

+1

per eseguire il backup di ogni file elaborato: sed -i.bak -f convert.sed $ f – lollinus

+0

'break' interrompe i cicli' for' e si può fare 'if prog || prog || prog' per OR logico (ma l'alternanza delle regex è migliore in questo caso). 'for' con' find' è di solito una cattiva idea perché fallisce quando i nomi dei file hanno spazi. È meglio mettere pipe 'find' in' while'. –

risposta

2

Non rifuggire da Perl: si fa questo tipo di compito facile!

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

L'interruttore -i è per la modifica sul posto. Crea automaticamente backup e scrive i risultati trasformati nelle posizioni originali.

L'impostazione @ARGV fa sì che il programma sia stato richiamato solo con i file *.cpp e *.hpp che contengono i vecchi nomi di classe. Il passaggio da -E a grep abilita le espressioni regolari estese in modo non scalato (, ) e | sono metacaratteri.

Se non ci fossero colpi (cioè, se @ARGV è vuota), allora non c'è niente da fare.

In caso contrario, per ogni riga di ogni file che ha i vecchi nomi (la meccanica di cui Perl gestisce per voi!), Provare a cambiare titolo Field_Blob_Medium-my::ns::MediumBlob e così via. Si noti che questi tentativi di sostituzione cessano dopo il primo successo, quindi se una riga contiene due nomi vecchi diversi, uno verrà sostituito e l'altro rimarrà lo stesso.

In genere l'operatore di sostituzione è scritto s///, ma è possibile utilizzare i delimitatori di bracketing come sopra. L'ho fatto per giustificare i nuovi nomi a sinistra.

Naturalmente questo è un sostituto per la tua sostituzione effettiva.

Infine, print la linea eventualmente modificata, che a causa di -i lo scrive nel file di origine aggiornato.

0

È possibile utilizzare l'opzione regex per grep per offrire maggiore flessibilità nella ricerca. Per il tuo esempio:

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

potrebbe essere

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

Si potrebbe stringa insieme quelli '|' s ai vostri cuori contenuto.

Inoltre si potrebbe unire i reperti nelle vostre greps

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

... nel caso in cui si vuole semplificare quel ciclo lì.

1

Questo lavoro sul mio Linux.Gestisce le varie cose appuntite da altri:

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

ciò che è importante:

  • la possibilità -print0 di trovare con l'-0 di xargs gestisce i file con gli spazi. Usa il carattere ASCII "null" come separatore. L'opzione -0 di xargs comprende il carattere "null" come separatore: gestisci correttamente i nomi di file con spazi.
  • l'opzione --replace viene usato per sostituire il '{}' stringa dal file elaborato corrente
  • l'opzione -i di schiene sed fino il file con un .save
  • Il & & lavoro come una scorciatoia di se. La seconda parte dell'espressione funziona solo se la prima parte è vero

speranza che helsp, MY2C

Problemi correlati