Search code examples
powershelltextextract

PowerShell Extract Number Between Square Brackets And Insert Into Following Line


I am trying to insert the item number extracted from preceding line. I have a file with groups of text that are numbered in square brackets.

For example

some text

line 1: [1]
line 2: id = Item 

line 1: [2]
line 2: id = Item 

Should be changed to:

some text

line 1: [1]
line 2: id = Item 1

line1: [2]
line 2: id = Item 2
$filepath = "D:\Users\j\Desktop\New folder\Environment-p.ini"
get-content $filepath | $itemnumber = select-string '(?<=\[)[^]]+(?=\])').matches.value | $iteminsertnumber = select-string -pattern "Item" | $iteminsertnumber.replace("Item","Item $itemnumber") | out-file "D:\Users\j\Desktop\New folder\Environment-p mod.ini"

$filepath = "D:\Users\j\Desktop\New folder\Environment-p.ini"
get-content $filepath | select-string -pattern "(?=\[).*?(?=\])" -context 0, 1 | foreach {$_.matches.value} | -replace $_.context.postcontext('Item',"Item $_") | set-content "D:\Users\j\Desktop\New folder\Environment-p mod.ini"

Solution

  • A switch with the -Regex flag could work for this, as an example:

    $content = @'
    some text
    
    line 1: [1]
    line 2: id = Item
    
    line 1: [2]
    line 2: id = Item
    
    line 1: [123]
    line 2: id = Item
    '@ -split '\r?\n'
    
    switch -Regex ($content) {
        '(?<=\[)[^\]]+' {
            # capture whats between brackets
            $value = $Matches[0]
            # output the line
            $_
            # go to next line
            continue
        }
        # if there was a capture previously
        { $value } {
            # replace the end of the line including
            # any possible whitespaces before it
            # with a space and the captured value
            $_ -replace '\s*$', " $value"
            # reset the value
            $value = $null
            # go to next line
            continue
        }
        # output this line if none of the above
        Default { $_ }
    }
    

    If you're reading a file you would use the -File parameter, logic is still the same:

    # this outer scriptblock allows us to pipe the output
    # from the switch to Set-Content
    & {
        switch -Regex -File $filepath {
            # same logic here
        }
    } | Set-Content path\to\resultfile.ext