2

I'm trying to comment out some code in a massive amount of files

The files all contain something along the lines of:

    stage('inrichting'){
        steps{
              build job: 'SOMENAME', parameters: param
              build job: 'SOMEOTHERNAME', parameters: param
              echo 'TEXT'
        }
    }

The things within the steps{ } is variable, but always exists out of 0..N 'echo' and 0..N 'build job'

I need an output like:

    //stage('inrichting'){
    //   steps{
    //        build job: 'SOMENAME', parameters: param
    //        build job: 'SOMEOTHERNAME', parameters: param
    //        echo 'TEXT'
    //  }
    //}

Is there any good way to do this with PowerShell? I tried some stuff with pattern.replace but didn't get very far.

$list = Get-ChildItem -Path 'C:\Program Files (x86)\Jenkins\jobs' -Filter config.xml -Recurse -ErrorAction SilentlyContinue -Force | % { $_.fullname };
foreach ($item in $list) {
...
}
3
  • are you trying to comment out anything which contains a 'steps' block? the entire file? anything with those variables in it? Commented Jul 20, 2018 at 8:48
  • also if it's the steps block, can you assume it will always be the same height (lines) or at least always have the same number of braces? Commented Jul 20, 2018 at 8:49
  • there's multiple stages, I only want to comment the stage('inrichting'){ stage. So only the steps block within this stage. We can assume the same number of brackets, the amount of lines varies. Commented Jul 20, 2018 at 8:55

1 Answer 1

1

This is a bit tricky, as you're trying to find that whole section, and then add comment markers to all lines in it. I'd probably write an ad-hoc parser with switch -regex if your structure allows for it (counting braces may make things more robust, but is also a bit harder to get right for all cases). If the code is regular enough you can perhaps reduce it to the following:

stage('inrichting'){
    steps{
        ... some amount of lines that don't contain braces
    }
}

and we can then check for occurrence of the two fixed lines at the start and eventually two lines with closing braces:

 foreach ($file in $list) {
    # lines of the file
    $lines = Get-Content $file
    # line numbers to comment out
    $linesToComment = @()
    # line number of the current block to comment
    $currentStart = -1
    # the number of closing braces on single lines we've encountered for the current block
    $closingBraces = 0

    for ($l = 0; $l -le $lines.Count; $l++) {
        switch -regex ($lines[$l]) {
            '^\s*stage\('inrichting'\)\{' {
                # found the first line we're looking for
                $currentStart = $l
            }
            '^\s*steps\{' {
                # found the second line, it may not belong to the same block, so reset if needed
                if ($l -ne $currentStart + 1) { $currentStart = -1 }
            }
            '^\s*}' {
                # only count braces if we're at the correct point
                if ($currentStart -ne -1) { $closingBraces++ }
                if ($closingBraces -eq 2) {
                # we've reached the end, add the range to the lines to comment out
                $linesToComment += $currentStart..$l
                $currentStart = -1
                $closingBraces = 0
                }
            }
        }
    }

    $commentedLines = 0..($lines.Count-1) | % {
      if ($linesToComment -contains $_) {
        '//' + $lines[$_]
      } else {
        $lines[$_]
      }
    } | Set-Content $file

 }

Untested, but the general idea might work.

Update: fixed and tested

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks a lot, took a bit of editing out some minor flaws with the code. but it worked!
You're welcome. Sorry for the flaws, but writing code right on SO is always fraight with problems ;). Parsing this way isn't pretty, but under certain constraints it can work well enough and is much easier to get right than "proper" approaches. It's still a hack job for every specific case, though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.