2

I'm modifying a bunch of python files and I need to prepend every variable declaration with 'self.'. Here's an example of what I'm trying to do.

From this:

class testClass(parentClass):
    def __init__(self):
        parentClass.__init__(self)

        flag1               = 0  
        flag2               = 1    

        array =           (0,
                           1,
                           2)

To this:

class testClass(parentClass):
    def __init__(self):
        parentClass.__init__(self)

        self.flag1               = 0  
        self.flag2               = 1    

        self.array =           (0,
                                1,
                                2)

I'm familiar with sed but I'm not sure how to prepend lines that don't match multiple strings/numbers. I.g. prepend line if it doesn't match the following patterns: ^'def' or ^'import' or ^'parentClass' or ^[0-9]. Any guidance would be very helpful. Thanks.

  • Is this only about __init__ methods or do you want to prepend self. in all class methods? – hoefling Aug 9 '18 at 22:50
0

This little perl one-liner will attempt to restrict the substitution to the __init__ method

perl -pe '
    if (/^\s* def \s+ __init__/x) {
        $start = 1;
    }
    elsif ($start) {
        s{ (\w+) (?=\s+=) }{self.$1}x;
        /^\s* (class | def) \b/x and $start = 0;
    }
' file.py

Or, the same logic in awk

awk '
    $1 == "def" && $2 ~ /^__init__/ {start = 1; print; next}
    start && /^[[:blank:]]+[[:alnum:]_]+)[[:blank:]]*=/ {
        $0 = gensub(/[[:alnum:]_]+/, "self.\\0", 1)
    }
    {print}
    $1 == "def" || $1 == "class" {start = 0}
' file.py
  • I'm assuming python variable names consist of letters, numbers and underscore. Please update my regex if I'm incorrect. – glenn jackman Aug 9 '18 at 22:04
0

Assuming the lines you want to apply the variable prepend to always have the = sign form you specified, this sed one-liner should work.

$ cat myfile.py 
class testClass(parentClass):
    def __init__(self):
        parentClass.__init__(self)

        flag1               = 0  
        flag2               = 1    

        array =           (0,
                           1,
                           2)
$ sed -e 's/\(^\s\+\)\(\w\+\)\(\s*=\)/\1self\.\2\3/g' myfile.py 
class testClass(parentClass):
    def __init__(self):
        parentClass.__init__(self)

        self.flag1               = 0  
        self.flag2               = 1    

        self.array =           (0,
                           1,
                           2)

That horrible looking regular expression is looking for lines that start with an alphanumeric string (ignoring whitespace), then have some spaces before an equal sign. It prepends self. to the variable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.