Steve Lorimer
Steve Lorimer

Reputation: 28669

use sed to replace one namespace with two

I have the following code layout:

#ifndef _file_h_
#define _file_h_

namespace FooBar
{
    // code
}

#endif

and I want to run this through sed and convert the FooBar namespace into Foo::Bar and add the closing brace

#ifndef _file_h_
#define _file_h_

namespace Foo { namespace Bar {

// code

}}

#endif

I will admit that my regular expression knowledge is quite poor at the best of times.

I think my command below is somewhere close to achieving what I'm looking for, but I'm getting some of the syntax wrong. Can someone please help?

cat file.h  | sed -e 's/(.*)namespace FooBar[\s\n]{(.*)}/\1namesapce Foo \{ namespace Bar \{\2\}\}/g' | less

Upvotes: 1

Views: 523

Answers (2)

sarnold
sarnold

Reputation: 104080

Knowing that the final brace will always be the last brace in the file gives me an idea that may work:

First, stealing Rob's first regex:

sed -ie 's/namespace FooBar/namespace Foo { namespace Bar/g;' file.h

Next, a new regex for the final brace:

perl -pi -e 's/^}$(.*?)\z/}}\1/ms' file.h

I switched to Perl for the second command so I could use its less-greedy *? operator, the ^ and $ and \z assertions, and the /ms modifier (to get friendly multi-line matching).

These two commands combined made the following changes on your sample file:

$ diff -u file.h.backup file.h
--- file.h.backup   2012-05-21 16:27:29.000000000 -0700
+++ file.h  2012-05-21 16:29:31.000000000 -0700
@@ -1,10 +1,10 @@
 #ifndef _file_h_
 #define _file_h_

-namespace FooBar
+namespace Foo { namespace Bar
 {
     // code
-}
+}}

 #endif

This is pretty brittle -- a full C++ language parser would be far more robust, though certainly not this easy to write. I hope whatever is left over is easy enough to deal with by hand.

Upvotes: 1

Rob I
Rob I

Reputation: 5737

Hopefully, the format of your header files is always like you've shown (namespace on its own line, opening/closing braces at beginning of line, etc).

If so, you don't need to worry about capturing here. Try:

sed -e 's/namespace FooBar/namespace Foo { namespace Bar/g; s/^}/}}/g;' file.h > file2.h

If not, take @sarnold's comment to heart - this will be difficult.

Upvotes: 1

Related Questions