Andrew Poland
Andrew Poland

Reputation: 185

How to replace text inside braces using Powershell?

I have the following powershell script running over a C# class in order to replace the constructor with an empty constructor. I am doing this over a number of files that were autogenerated.

$nl = [Environment]::NewLine
foreach($item in Get-ChildItem $path) {            
        if($item.extension -eq ".cs") {

            $name = $item.name
            $name = $name.replace('.cs', '')
            $reg = '(public ' + $name + '\(.*?\})'
            $constructorString = [regex]$reg
            $emptyConstructor = 'public ' + $name + '()' + $nl + '{' + $nl + '}' + $nl


            Get-Content $item.fullname -Raw | Where-Object { $_ -match $constructorString } | ForEach-Object { $_ -replace $constructorString, '$1'}            
        }
}

The classes have a form of

public Bar()
{
    this.foo = new Foo();
}

This results in no matches, let me know if more information is required.

Upvotes: 0

Views: 273

Answers (1)

Keith Hill
Keith Hill

Reputation: 201602

There is no need to convert the pattern to a regex. Try this:

$item | Get-Content -raw | Where {$_ -match "(?s)(public\s+${name}\s*\(.*?\})"} | ...

I believe the issue you are running into is that although you've read the C# file as a single string using the -Raw parameter, there are line breaks in the string that .* won't traverse unless you use singleline mode in the regex. That is what the (?s) does.

Also, if you are on PowerShell V3 you can use basename instead of replace e.g.:

$name = $item.basename

BTW have you looked at Roslyn as an alternative to the regex search/replace approach? Roslyn will build an AST for you for each source file. With that you could easily find default constructors and replace it with an empty constructor.

Upvotes: 2

Related Questions