How to - Find and replace the first occurrence only

戏子无情 提交于 2021-02-11 12:34:47

问题


I have a script that seems to work correctly only it works to good. I have files that contain multiple lines with the string "PROCEDURE DIVISION.", with the period at the end.

What I need to do...

ONLY remove the [2nd occurrence] of the string "PROCEDURE DIVISION." if it's in the text file twice and bypass the file if it is only found once. I need to preserve the 1st occurrence and change/remove the 2nd occurrence.

I can find and replace all the occurrences easily, I have no clue how to replace only 1 of 2.

Is this possible using Powershell?

Here is my code so far...

Get-ChildItem 'C:\Temp\*.cbl' -Recurse | ForEach {#
     (Get-Content $_ | ForEach   { $_ -replace "PROCEDURE DIVISION\.", "                   "}) | Set-Content $_ 
} 

UPDATE

I got this to work and it's not pretty.

The only problem is is is capturing the string in the comments section. What I need to do is only count the string as a hit when it's found starting in position 8 on each line.

Is that possible?

Get-ChildItem 'C:\Thrivent\COBOL_For_EvolveWare\COBOL\COBOL\*.*' -Recurse | ForEach {
     ($cnt=(Get-Content $_ | select-string -pattern "PROCEDURE DIVISION").length)
     if ($cnt -gt "1") {
        (Get-Content $_ | ForEach   { $_ -replace "PROCEDURE DIVISION\.", "                   "}) | Set-Content $_
           $FileName = $_.FullName
           Write-Host "$FileName = $cnt" -foregroundcolor green
      } 

回答1:


There are potential issues with all of the provided answers. Reading a file using switch statement is likely going to be the fastest method. But it needs to take into account PROCEDURE DIVISION. appearing multiple times on the same line. The method below will be more memory intensive than using switch but will consider the multi-match, single line condition. Note that you can use -cmatch for case- sensitive matching.

# Matches second occurrence of match when starting in position 7 on a line
Get-ChildItem 'C:\Temp\*.cbl' -Recurse -File | ForEach-Object {
    $text = Get-Content -LiteralPath $_.Fullname -Raw
    if ($text -match '(?sm)(\A.*?^.{6}PROCEDURE DIVISION\..*?^.{6})PROCEDURE DIVISION\.(.*)\Z') {
        Write-Host "Changing file $($_.FullName)"
        $matches.1+$matches.2 | Set-Content $_.FullName
    }
}
    



回答2:


This maybe a bit of a hack, but it works. $myMatches = $pattern.Matches in the case below gives us 3 matches, $myMatches[1].Index is the position of the second occurrence of the string you want to replace.

$text = "Hello foo, where are you foo? I'm here foo."

[regex]$pattern = "foo"

$myMatches =  $pattern.Matches($text)

if ($myMatches.count -gt 1)
{
  $newtext = $text.Substring(0,$myMatches[1].Index) + "bar" + $text.Substring($myMatches[1].Index + "foo".Length)

  $newtext
}



回答3:


try this:

$Founded=Get-ChildItem 'C:\Temp\' -Recurse -file -Filter "*.cbl" | Select-String -Pattern 'PROCEDURE DIVISION.' -SimpleMatch | where LineNumber -GT 1 | select Path -Unique
$Founded | %{

$Nb=0
$FilePath=$_.Path

$Content=Get-Content $FilePath | %{
    if($_ -like '*PROCEDURE DIVISION.*')
    {
           $Nb++

           if ($Nb -gt 1)
           {
                $_.replace('PROCEDURE DIVISION.', '')
           }
           else
           {
                $_
           }
    }
    else
    {
      $_
    }


}

$Content | Set-Content -Path $FilePath

}



回答4:


You could use switch for this:

Get-ChildItem -Path 'C:\Temp' -Filter '*.cbl' -File -Recurse | ForEach-Object {
    $occurrence     = 0
    $contentChanged = $false
    $newContent = switch -Regex -File $_.FullName {
        'PROCEDURE DIVISION\.' { 
            $occurrence++
            if ($occurrence -eq 2) {
                $_ -replace 'PROCEDURE DIVISION\.', "                   "
                $contentChanged = $true
            }
            else { $_ }
        }
        default { $_ }
    }
    # only rewrite the file if a change has been made
    if ($contentChanged) {
        Write-Host "Updating file '$($_.FullName)'"
        $newContent | Set-Content -Path $_.FullName -Force
    }
}


来源:https://stackoverflow.com/questions/65672400/how-to-find-and-replace-the-first-occurrence-only

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!