tags:

views:

191

answers:

2

I have several C# classes where the namespace wasn't added to the file. A sample file looks like this (Test.cs):

using System;
using System.IO;

public partial class MyTestClass
{
    protected void MyTestVoid()
    {
        // Magic happens here
    }
}

As you can see there is no namespace declaration. I want the output to be:

using System;
using System.IO;

namespace MyNamespace
{
    public partial class MyTestClass
    {
       protected void MyTestVoid()
       {
            // Magic happens here
       }
    }
}

What I am trying to do is write a quick script to basically insert the namespace around the class definition. I decided to try awk out and so I created an awk file like so:

$0 ~ "namespace MyNamespace"
{
    foundTrigger = 1;
}

!foundTrigger
{
    if ($0 ~ "/^[:space:]*public[:space:]{1}(partial[:space:])*class/")
    {
        print "namespace MyNamespace\n{\n" $0;
    }
    else
    {
        print $0;
    }
}

END
{
    if (!foundTrigger)
        print "}";
}

After executing this for a file (like the one above), it doesn't really do anything (aside from adding the "}" to the bottom of the file).

This is how I understand my regex to be used:

^[:space:]*public[:space:]{1}(partial[:space:])*class

The line must start with zero or more spaces followed by the word "public" followed by exactly one space followed by zero or more ("partial" followed by a space) followed by the word "class". Therefore these lines should match:

public class Test
public partial class Test

And these won't match:

public void Test()
public string Test

However if I use a similar regex for egrep:

egrep "^[[:space:]]*public[[:space:]]{1}(partial[[:space:]])*class" *.cs

I get this result:

public partial class MyTestClass

Reading the man pages of awk shows that:

Regular expressions are the extended kind found in egrep.

So I am not sure why my awk script isn't working. Any help is appreciated. Perhaps there is a better way to accomplish what I am trying to do?

A: 

Maybe it helps to look at the problem a little differently. Instead of trying to match the line after/before with a regex, try grabbing the entire using "paragraph" itself. Append to that, and finish the file.

    BEGIN { 
        RS = ""; # Read by "paragraphs".  
                 # Records are separated by blank lines. 
    }
    {
        if ( NR == 1 )
        {
            print $0,"\n\nnamespace MyNameSpace;\n{";
            RS = "\n";
        }
        else
        {
            print "\t", $0;  # For indenting
        }
    }
    END {
        print "}";
    }

Edit: Originally I inserted a "using" directive. He wanted "namespace" (and appropriate syntax): an almost identical problem. Fixed.

clintp
I modified yours a little bit to suit my needs:BEGIN { RS = ""; # Read by "paragraphs". # Records are separated by blank lines. } { if ( NR == 1 ) { print $0,"\nnamespace MyNameSpace\n{\n"; RS = "\n"; # Reset the record separator } else { print $0; } }
smoak
Oh duh. I solved the wrong problem (using/namespace), the right way. :) Glad it worked for you.
clintp
A: 

This should do it:

/^ *public (partial )*class / {trigger = 1 ; print "namespace MyNamespace"}
{print $0}
END {if(trigger) print "} //end of space"}

But you seems awfully strict about whitespace. I'd loosen it up a little, but then I don't trust my own typing.

Beta