Script to change C ++ class names

I have moved my classes from the global namespace to a specific namespace. I also changed the class names. I want to convert all source files that use these classes to a new format. I thought either a bash script, using a sed file on Cygwin, or running a perl script. I have problems with a bash script.

Here is the process I'm trying to execute:

  • For each source file * .cpp and * .hpp, recursively:
  • If the file contains the old class name, then convert the file.
  • End for.

My problem in a bash script detects if the file contains the old class name. I was thinking of one grep expression for each class name:

 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 

The problem is that only one command can be in a bash if expression using this syntax:

 if grep "Field_Unsigned_Short" $f; 

so i cant make boolean OR from grep s.

I could execute a nested loop, but I don't know how to break out of the bash for loop:

 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 

So, I am looking for suggestions on how to process each source file containing old class names and convert them to new ones. A preferred example is a Cygwin bash script, although a Perl script would also be acceptable. In addition, the script must backup the original source file before writing the converted content to the new file.

I am running Cygwin on Windows XP and Windows Vista.

+6
c ++ bash perl sed cygwin
source share
3 answers

Do not shy away from Perl: it makes the task easier!

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

The -i switch is for on-site editing. It automatically backs up and records converted results to the original locations.

Configuring @ARGV makes it as if you were only @ARGV program with those *.cpp and *.hpp that contain old class names. The -E switch on grep allows you to use extended regular expressions, so unescaped ( , ) and | are metacharacters.

If there were no hits (i.e. if @ARGV empty), then there is nothing to do.

Otherwise, for each line of each file that has old names (the mechanics of which Perl processes for you!), Try renaming Field_Blob_Medium to my::ns::MediumBlob and so on. Note that these substitution attempts stop after the first success, so if the line contains two different old names, one will be replaced and the other will remain the same.

Normally, the lookup operator is written s/// , but you can use the bracketing delimiters as described above. I did this to the left - to justify the new names.

Of course, this is a backup system for your real substitution.

Finally, print possibly a modified line, which, due to -i writes it to the updated source file.

+2
source share

This work is on my Linux. He manages various things indicated by others:

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

What is important:

  • the -print0 option to search with -0 from xargs manages files with spaces. It uses the "null" ASCII char as a delimiter. The -0 xargs parameter understands the "null" char as a delimiter: you correctly manage file names with spaces.
  • the -replace option is used to replace the string '{}' with the current processed file
  • -i sed option supports file with .save
  • && act as if. The second part of the expression only works if the first part is correct.

Hope this is helsp, my2c

+1
source share

You can use the regex option for grep to give you more flexibility in your search. In your example:

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

may be

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

You can combine these "| to your heart.

Plus you can combine your finds into your greps

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

... if you want to simplify this cycle.

0
source share

All Articles