3

I have a few hundred files which all contain variations of the same class, 'Process'. My intention is to make each class a derived class of some base clase 'BaseProcess'. Every file has been manually renames to something like 'Process_XXX' and I am trying to find a way of going through every file and changing every occurrence of, for example:

class Process {
    stuff;
}

to

class Process_XXX : public BaseProcess {
    stuff;
}

where XXX is taken from the particular file being changed. Is this possible using Bash or Perl scripting? Or is it best to proceed manually? Cheers Jack

JMzance
  • 1,704
  • 4
  • 30
  • 49
  • Are the files actually named `Process_XXX`, or do they also have some extension? – TLP Jul 22 '13 at 13:19
  • The names in my question are just examples. They are actually things like: CPPProcess2j_ud.cc which has a header file CPPProcess2j_ud.h and here XXX = ud – JMzance Jul 22 '13 at 15:02
  • That seems like a rather important piece of information you left out there. – TLP Jul 22 '13 at 16:16

3 Answers3

2

I'll add an answer taking into account the file extensions (adding the changes I suggested to the answer by fedorqui) as well as improvements from DVK's answer:

for SUFFIX in cc h java txt; do
    for file in *.$ext; do
        sed -i.bak "s#^\\(\\s*class\\s\\+Process\\)\\(\\s*{\\)#\\1_${file/%.$SUFFIX} : public BaseProcess\2#g" $file
    done
done

An example of the pattern is s#^\(\s*class\s\+Process\)\(\s*{\)#\1_AlertGenerator : public BaseProcess\2#g with the XXX being AlertGenerator . I'm using the two \(...\) to extract the matches and use them in the replacement pattern as \1 and \2 (called back references in info sed).

Community
  • 1
  • 1
Samveen
  • 3,482
  • 35
  • 52
1

If files are in the same dir and have a same pattern name like file, this can make it:

for file in file*
do
   sed -i.bk "s/Process/Process_$file : public BaseProcess/g" $file
done

Note that with -i.bk a backup file $file.bk will be created.

Tested successfully with three files: file1, file2, file3.

fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • Hi, using this I get the error 'sed: -i may not be used with stdin' For every file. Thanks for the help – JMzance Jul 22 '13 at 13:07
  • Can you try just `sed -i "s/process...` (without `sed -i.bk`)? Make sure you make a backup of your files, because they will be replaced with this command. – fedorqui Jul 22 '13 at 13:10
  • use `"s/Process/Process_${file/%.$SUFFIX} : public BaseProcess/g"` as the parameter to `sed` with the appropriate `SUFFIX=` definition (for eg `SUFFIX=java`) That takes into consideration the filename extensions – Samveen Jul 22 '13 at 13:11
  • Just for the record, I just posted a new question related to this one: http://stackoverflow.com/questions/17788947/how-to-use-the-name-of-the-file-with-sed-in-a-find-expression – fedorqui Jul 22 '13 at 13:38
1
perl -pi.bak -e \
   's#^\s*class Process {#class Process : public BaseProcess_$ARGV {#g;' \
   Process_XXX
mv *.bak /your/backup/directory

This is similar to SED's solution (part of Perl's roots are in sed :) but the benefit is that it can be easily extended if more complicated tasks are needed. E.g. if your files are in various sub-directories, you can use Perl's File::Find; or you can rename the files if needed.

DVK
  • 126,886
  • 32
  • 213
  • 327
  • Using this Perl method, does XXX get replaced with whatever values are at the end of the filename? – JMzance Jul 22 '13 at 13:17
  • You can use `$ARGV` to get the file name. – TLP Jul 22 '13 at 13:18
  • @JackMedley - it does now. Sorry missed that part from the Q. – DVK Jul 22 '13 at 13:19
  • @DVK - Thanks for your help. I'm having a little trouble running the script. I run: perl -pi.bak -e 's#^\s*class CPPProcess{#class CPPProcess_$ARGV : public CPPProcess {#g;' CPPProcess2j* In the hopes of changing class definitions such as: class CPPProcess {... (in file CPPProcess_bc.h) into: class CPPProcess_bc : public CPPProcess {... But none of the files seem to be changed at all? – JMzance Jul 22 '13 at 16:15