1

I am trying to replace only the first occurrence of a string found within a bunch of text files. I have spent hours on this and can't seem to fix it.

I couldn't get this to work. PowerShell Script to Find and Replace for all Files with a Specific Extension

$text_file_ext = 'txt'
Get-ChildItem $base_dir -Recurse -Include "*.$text_file_ext" |
ForEach-Object { (Get-Content $_.FullName) | 

foreach -Begin { $found = $false; $search = 'APPLE' } -Process {
if (! $found -and ($_ -match $search))
{
    $_ = $_ -replace $search, ' COFFEE'
    $found = $true
}
#$_
Set-Content $_.FullName}
}

I also referenced this: http://www.adamtheautomator.com/use-powershell-to-do-a-findreplace-on-a-set-of-text-files/

Sample Text

Lorem ipsum APPLE dolor sit amet, consectetur adipiscing elit. Donec a pharetra nisl, vitae APPLE vehicula turpis. Aenean eleifend bibendum quam, nec dapibus felis viverra ut. Mauris nec nibh scelerisque, aliquet ligula in, viverra justo. Interdum et malesuada fames ac APPLE ante ipsum primis in faucibus.

Any advice is appreciated.

Final Version Working

$search ="APPLE"
$text_file_ext = 'txt'
Get-ChildItem $base_dir -Recurse -Include "*.$text_file_ext" |
ForEach-Object { (Get-Content $_.FullName -Raw) -replace" (.+?)$search(.+)",'$1COFFEE$2'|
Set-content $_.Fullname
}
Community
  • 1
  • 1
wp44
  • 265
  • 1
  • 4
  • 13

1 Answers1

2

It will be easier if you can deal with the file as a single string.

If you have V3 or better you can add the -Raw switch:

(Get-Content $_.FullName -Raw)

For earlier versions, you can pipe through Out-String:

(Get-Content $_.FullName | Out-String)

Then user a regex with a lazy match:

(Get-Content $_.FullName -Raw) -replace "(.+?)$search(.+)",'$1COFFEE$2'|
 Set-content $_.Fullname
Frode F.
  • 52,376
  • 9
  • 98
  • 114
mjolinor
  • 66,130
  • 7
  • 114
  • 135
  • `Set-Content` will add extra newline at the end of file. – user4003407 Mar 06 '16 at 21:53
  • Thank you Gentlemen for your help I have done this : $search ="APPLE" $text_file_ext = 'txt' Get-ChildItem $base_dir -Recurse -Include "*.$text_file_ext" | ForEach-Object { (Get-Content $_.FullName -Raw) -replace "(.+?)$search(.+)",'$1COFFEE$2'| Set-content $_.Fullname - I am sure it is not right the way I am writing it? – wp44 Mar 06 '16 at 22:07
  • Are you not getting the expected results? – mjolinor Mar 06 '16 at 22:12
  • Thankyou mjolinor - it replaced the first occurrence as it was meant to . Great work :) – wp44 Mar 06 '16 at 22:25
  • Just a quick follow up - if I wanted to replace the first occurrence as brackets () - I have done $search ="\(\)" - it replaced all the brackets - any way I can have the first set of brackets only thank you – wp44 Mar 06 '16 at 22:35
  • Try running $search through [regex]::Escape() first -> $search = [regex]::excape($search). – mjolinor Mar 06 '16 at 22:52
  • For Some reason it replaces the first 2 sets of () brackets it finds - but leaves the rest alone - I'm not sure what it could be – wp44 Mar 06 '16 at 23:15
  • Post another question, including your code and sample data. – mjolinor Mar 06 '16 at 23:30
  • $search ="()" $search = [regex]::Escape($search) $text_file_ext = 'txt' Get-ChildItem $base_dir -Recurse -Include "*.$text_file_ext" | ForEach-Object { (Get-Content $_.FullName -Raw) -replace "(.+?)$search(.+)",'$1COFFEE$2'| Set-content $_.Fullname} - thank you -Sample data same as above but () instead of APPLE – wp44 Mar 06 '16 at 23:35