replacing more text strings with certain text strings in powershell - powershell

my code replace one text for another text well
$pathhh = "E:\times"
$searchWords = 'NEWYORK'
$replaceWord = 'CANCELED'
Foreach ($sw in $searchWords)
{
Get-Childitem -Path $pathhh -Recurse |
Select-String -Pattern "$sw" |
Select Path,LineNumber,#{n='SearchWord';e={$sw}}
}
if (1 -eq 1) {
$files = Get-Childitem -Path $pathhh -File -Recurse
foreach ($file in $files) {
$content = get-content -raw $file.PSPath
# regex may have problems
$content = $content -replace $searchWords,
$replaceWord
set-content $file.PSPath $content
}
}
but I need more different replacements like
replace NEWYORK with CANCELLED and replace LA with INFO and replace LONDON with DELAYED so more text replacements so like
$searchWords = 'NEWYORK,LA,LONDON'
$replaceWord = 'CANCELED,INFO,DELAYED'
but have no idea how to connect it all together thank you for your help!

Instead of using two comma delimited strings as you are trying now, I would suggest creating a replacements map (Hashtable) to store the words to replace and their replacement strings in one easy to use structure.
Something like this:
$replacements = #{
'NEWYORK' = 'CANCELLED'
'LA' = 'INFO'
'LONDON' = 'DELAYED'
}
$files = Get-Childitem -Path $pathhh -File -Recurse
foreach($file in $files) {
$content = Get-Content -Path $file.FullName -Raw
foreach ($item in $replacements.Keys) {
$content = $content.Replace($item, $replacements[$item])
}
Set-Content -Path $file.FullName -Value $content
}

Related

Power shell code to remove special characters in the column headers(.csv file)

I'm trying to loop through 40 CSV files in a path and remove any characters that are not numeric,alphabets and space values only in the headers.
Below is my code i tried working on, This is working for headers in the files but also its replacing all the data in the file and i can see only headers without special characters in it, i'm just a beginner in power shell, not sure how to proceed further any help is much appreciated.
$path = "C:\AllFiles\"
Get-ChildItem -path $path -Filter *.csv |
Foreach-Object {
$content = Get-Content $_.FullName
$content[0] = $content[0] -replace '[^0-9a-zA-Z, ]'|Set-Content $_.FullName
}
The -replace operator requires two values, the first value is what you are looking for, and the second value is what to replace the first value with.
EXAMPLE:
"John Jones" -replace "Jones","Smith"
This will replace "Jones" with the text "Smith" creating a new string "John Smith"
In your example, instead of creating a regex of what you want to keep, create a regex of what you want to replace.
EXAMPLE:
$path = "C:\AllFiles\"
Get-ChildItem -path $path -Filter *.csv |
Foreach-Object {
$content = Get-Content -Path $path
$content[0] = $content[0] -replace '[regex for special chars]',""
Set-Content $path -value $content -force
}
This will replace the whole string, with a string where you've replaced the regex values with ""
This should do the trick and should be the fastest method:
$path = 'C:\AllFiles\'
$collection = Get-ChildItem -path $path -Filter *.csv'
foreach( $file in $collection ) {
$content = [System.IO.File]::ReadAllLines( $file.FullName )
$content[0] = $content[0] -replace '[^0-9a-zA-Z, ]'
[System.IO.File]::WriteAllLines( $file.FullName, $content ) | Out-Null
}
Pretty close, try it like this instead:
$path = "C:\temp"
Get-ChildItem -path $path -Filter *.csv |
Foreach-Object {
$content = Get-Content $_
$content[0] = $content[0] -replace '[^a-zA-Z0-9, ]',''
$content | Out-File $_
}
This will only clear special characters on the first line but leaves the rest of the file untouched.
Try this:
dir "C:\AllFiles" -Filter *.csv | % {
(Get-Content $_.FullName)[0] -replace '[\W]', '' | Set-Content $_.FullName -Force
}

Issue with nested powershell

I have this code snippet where I try tro replace some strings in all files of a directory. I thought I could nest the foreach in the ForEach-Object, but this does not seem to work.
The error I get is:
InvalidArgument: (:) [ForEach-Object], ParameterBindingException
$files = Get-ChildItem $testdir\reference *.* -recurse
$replacementMap = #{"Fruit::Apple" = "NewApple";"Fruit::Banana" = "NewBanana"}
foreach ($file in $files)
{
If (Get-Content $($file.FullName) | Select-String -Pattern "Fruit::")
{
$content = Get-Content $($file.FullName) | ForEach-Object
{
$line = $_
foreach ($entry in $replacementMap.GetEnumerator())
{
$line -replace $($entry.Name),$($entry.Value)
}
}
$content = $content -join "`r`n"
$content | Set-Content $($file.FullName)
}
This code worked without the
foreach ($entry in $replacementMap.GetEnumerator())
{
$line -replace $($entry.Name),$($entry.Value)
}
part. Anyone has a clue what I'm doing wrong? Thanks in advance
You missed a curly brace closure and formatting issue on the foreach-object. You need to take care of foreach and foreach-object in a different way:
Replace your existing foreach part with this:
foreach ($file in $files)
{
If(Get-Content $($file.FullName) | Select-String -Pattern "Fruit::")
{
$content = Get-Content $($file.FullName) | %{
$line = $_
foreach ($entry in $replacementMap.GetEnumerator())
{
$line -replace $($entry.Name),$($entry.Value)
}
}
$content = $content -join "`r`n"
$content | Set-Content $($file.FullName)
}
}
Instead of processing the files line-wise, just do the replacement operation on the entire file content at once. If the content has changed, overwrite the file.
$replacementMap = #{
"Fruit::Apple" = "NewApple"
"Fruit::Banana" = "NewBanana"
}
Get-ChildItem $testdir\reference -File -Recurse | foreach {
$content = Get-Content $_
$dirty = $false
foreach ($key in $replacementMap.Keys) {
$content = $content -replace $key,$replacementMap.$key
$dirty = $true
}
if ($dirty) { $content | Set-Content $_ }
}

Powershell replace adding an empty line

I have this powershell code which should replace every occurrence of a string in every file in the directory with a new string.
This works, however an empty line is added in the end.
What causes this, and how can this be nicely avoided?
$files = Get-ChildItem $currentDir *.* -recurse
foreach ($file in $files)
{
$find = "placeholder"
$replace = "newvalue"
$content = Get-Content $($file.FullName) -Raw
$content -replace $find,$replace | Out-File $($file.FullName)
}
Simply removing the last line is not a good solution since sometimes my files will contain an empty line which I want to keep.
You could use the -NoNewline parameter to prevent Out-File from appending the extra line at the end of the file.
$content -replace $find,$replace | Out-File $($file.FullName) -NoNewline
Note: this was added in PowerShell 5.0
I am limited to PS version 4, and this is what I used
$files = Get-ChildItem $currentDir . -recurse
$find = "placeholder"
$replace = ""newvalue"
foreach ($file in $files)
{
$content = Get-Content $($file.FullName) -Raw | ForEach-Object { $_ -replace $find,$replace}
$content = $content -join "`r`n"
$content | Set-Content $($file.FullName)
}
Note that this only works if it is ok to store the complete file in memory.

Read txt file in folder and fint some text by per sample

I try to read big data log file, in folder C: \ log \ 1 \ i put 2 txt files, i need open-> read all file .txt and find with filter some text like whis: [text]
# Filename: script.ps1
$Files = Get-ChildItem "C:\log\1\" -Filter "*.txt"
foreach ($File in $Files)
{
$StringMatch = $null
$StringMatch = select-string $File -pattern "[Error]"
if ($StringMatch) {out-file -filepath C:\log\outputlog.txt -inputobject $StringMatch}
}
# end of script
not work
Would doing something like a select-string work?
Select-String C:\Scripts\*.txt -pattern "SEARCH STRING HERE" | Format-List
Or if there are multiple files you are wanting to parse maybe use the same select-string but within a loop and output the results.
$Files = Get-ChildItem "C:\log\1\" -Filter "*.txt"
foreach ($File in $Files)
{
$StringMatch = $null
$StringMatch = select-string $File -pattern "SEARCH STRING HERE"
if ($StringMatch) {out-file -filepath c:\outputlog.txt -inputobject $StringMatch}
}
This will print out the file name along with the line number in the file. I hope this is what you are looking for.
Remove-Item -Path C:\log\outlog.txt
$Files = Get-ChildItem "C:\log\1\" -Filter "*.txt"
foreach ($File in $Files)
{
$lineNumber = 0
$content = Get-Content -Path "C:\log\1\$File"
foreach($line in $content)
{
if($line.Contains('[Error]'))
{
Add-Content -Path C:\log\outlog.txt -Value "$File -> $lineNumber"
}
$lineNumber++
}
}
Code below works
It selects strings in txt files in your folder based on -SimpleMatch and then appends it to new.txt file.
Though i do not know how to put two simple matches in one line. Maybe someone does and can post it here
Select-String -Path C:\log\1\*.txt -SimpleMatch "[Error]" -ca | select -exp line | out-file C:\log\1\new.txt -Append
Select-String -Path C:\log\1\*.txt -SimpleMatch "[File]" -ca | select -exp line | out-file C:\log\1\new.txt -Append
Regards
-----edit-----
If you want to you may not append it anywhere just display - simply dont pipe it to out-file
use index then check it :
New-Item C:\log\outputlog.txt
$Files = Get-ChildItem "C:\log\1\" -Include "*.txt"
foreach ($File in $Files)
{
$StringMatch = $null
$StringMatch = Get-Content $File
if($StringMatch.IndexOf("[Error]") -ne -1)
{
Add-Content -Path C:\log\outputlog.txt -Value ($StringMatch+"
-------------------------------------------------------------
")
}
}
# end of script

Replace string content between quotes in file

I have made this loop to iterate some files that I want to replace content in.
The content that I want to replace is a string which can look something like this: foo="1".
What I need your help with is how to find the string (regexp I guess) and update the file with a new value, like 2 for example.
$files = Get-ChildItem -Recurse -Filter "*.config"
foreach ($file in $files)
{
Get-Content $file.FullName
}
Read-Host
From the sample code in the question, I assume you're attempting to update a .NET configuration file (ie. a web.config or app.config file).
Given that these files are really XML files, you may want to treat them as such:
$files = Get-ChildItem -Recurse -Filter "*.config"
foreach ($file in $files)
{
# Create an XmlDocument object from the file
$configXml = [xml](Get-Content $file.FullName)
# Find all the nodes in the document
$xmlNodes = $configXml.SelectNodes('//*')
# Keep track of whether we make changes or not
$changeCount = 0
foreach($node in $xmlNodes)
{
# Check if node has a "foo" attribute
if($node.HasAttribute('foo'))
{
# Set 2 as the value
$node.SetAttribute('foo',2)
$changeCount++
}
}
if($changeCount)
{
# At least one node was updated, save to file
$configXml.Save($file.FullName)
}
}
You can try regex. Ex.
$files = Get-ChildItem -Recurse -Filter "*.config"
$find = 'foo=".*?"'
$replace = 'foo="4"'
foreach ($file in $files)
{
Get-Content $file.FullName |
Foreach-Object { $_ -replace $find, $replace } |
Set-Content $file.Fullname
}
}
Read-Host
Or to only modify files that match:
$files = Get-ChildItem -Recurse -Filter "*.config"
$find = 'foo=".*?"'
$replace = 'foo="4"'
foreach ($file in $files)
{
$content = Get-Content $file.FullName
if(Select-String -InputObject $content -Pattern $find -Quiet) {
$content |
Foreach-Object { $_ -replace $find, $replace } |
Set-Content $file.Fullname
}
}
Read-Host
This should answer your question
$files = Get-ChildItem -Recurse -Filter "*.config"
foreach ($file in $files)
{
$fileContent = Get-Content $file.FullName
$newContent = $fileContent -replace 'foo="1"', 'foo="2"'
Set-Content $file.FullName $newContent
}
Further reading here: Use PowerShell to Replace Text in Strings