Python - RegExp - Modify text files
Question: Newbie to Python.... help requested with the following task :-)

I have tree of various files, some of them are C source code. I would like to
modify these C files with python script.

The C code has 4 defines -

    
    
    #define ZR_LOG0(Id, Class, Seveity, Format)
    #define ZR_LOG1(Id, Class, Seveity, Format, Attr0)
    #define ZR_LOG2(Id, Class, Seveity, Format, Attr0, Attr1)
    #define ZR_LOG3(Id, Class, Seveity, Format, Attr0, Attr1, Attr2)
    

there are various ZR_LOGn lines spread throughout the C source code.

Example: ZR_LOG1 (1, LOG_CLASS_3, LOG_INFO, "hello world %d", 76);

White spaces (spaces, tabs) may appear anywhere in the line (between the
fields).

The python script task is as follow:

  1. Replace any 'Id' field (which is an integer type that we don't care about its original value) with sequential counter. (The first 'LOG'... line we'll encounter the 'Id' field will get the value 0, the next one 1, and so on)
  2. In a separate output file, for each ZR_LOG line, we'll create an index line in the format _{ NewId, Format },_ For the example above will get:
    
        { 0, "hello world %d" },
    

Appreciate your help with it....

* * *

I have started with the following code, you may either look at it or ignore it
altogether.

    
    
    '''
    Created on Oct 25, 2009
    
    @author: Uri Shkolnik
    
    The following version does find & replace LOG Ids for all 
    C source files in a dir (and below) with sequential counter, 
    The files are assumed to be UTF-8 encoded. 
    (which works fine if they are ASCII, because ASCII is a 
    subset of UTF-8)
    It also assemble new index file, composed from all new IDs and format fields
    
    '''
    
    import os, sys, re, shutil
    
    mydir= '/home/uri/proj1'
    searched_pattern0 = 'ZR_LOG0'
    
    def search_and_replace(filepath):
        ''' replaces all string by a regex substitution '''
        backupName=filepath+'~re~'
    
        print 'reading:', filepath
        input = open(filepath,'rb')
        s=unicode(input.read(),'utf-8')
        input.close()
    
        m = re.match(ur'''[:space:]ZR_LOG[0-3].*\(.*[0-9]{0,10},LOG_''', s)
        print m
    
    def c_files_search(dummy, dirr, filess):
        ''' search directories for file pattern *.c '''
        for child in filess:
            if '.c' == os.path.splitext(child)[1] and os.path.isfile(dirr+'/'+child):
                filepath = dirr+'/'+child
                search_and_replace(filepath)
    
    os.path.walk(mydir, c_files_search, 3)
    


Answer: A few points:

  * You can match whitespace with '\s'.
  * The regexp 'capturing groups' are useful here.

So, I would do something like this:

    
    
    output = ''
    counter = 1
    for line in lines:
        # Match only ZR_LOG lines and capture everything surrounding "Id"
        match = re.match('^(.*\sZR_LOG[0-3]\s*\(\s*)'  # group(1), before Id
                         'Id'
                         '(,.*)$',  # group(2), after Id
                         line)
        if match:
            # Add everything before Id, the counter value and everything after Id
            output += match.group(1) + str(counter) + match.group(2)
            counter += 1
            # And do extra logging etc.
        else:
            output += line
    

