Powershell script causing a strange character in the output - powershell

I have this script:
# Read in the RESOURCE ID values I want to locate
$TextToFind = Get-Content -Path .\ResourceIDs.txt
$Text = ""
$PathArray = #()
$Results = ".\ResultsResourceIDs.txt"
# Now iterate each of these text values
$TextToFind | ForEach-Object {
$Text = $_
Write-Host "Checking for: " $Text
If ((Get-Content .\Resources.rc) | Select-String -Pattern $Text) {
$PathArray += $Text + "¬Found"
}
Else {
$PathArray += $Text + "¬Not Found"
}
}
Write-Host "Contents of ArrayPath:"
$PathArray | ForEach-Object {$_}
$PathArray | % {$_} | Out-File $Results
It works fine. But the resulting text file has content like:
IDR_ANNOUNCE_TEXT¬Not Found
IDC_BUTTON_UNDO¬Found
IDS_STR_CBS2¬Not Found
Why does it have the strange character?

This is due to encoding, you should use set_content CmdLet and you can play on -encoding param if necessary.
$PathArray | % {$_} | Set-Content $Results -Encoding UTF8

Related

Powershell text procesing: Join specific lines of a txt file

I have to process some text and got some difficulties:
The text .\text.txt is formatted like that:
name,
surname,
address,
name.
surname,
address,
etc.
What I want to achieve is join the objects that ends with the "," like this:
name,surname,address
name,surname,address
etc
I was working on something like this:
$content= path to the text.txt
$result= path to the result file
Get-Content -Encoding UTF8 $content | ForEach-object {
if ( $_ -match "," ) {
....join the selected lines....
}
} |Set-Content -Encoding UTF8 $result
What I need to consider is also that lines which terminate with "," may have a next line empty which should be a CR in the $result
You can do this by splitting the blocks of data on the empty newlines first:
# read the content of the file as one single multiline string
$content = Get-Content -Path 'Path\To\The\file.txt' -Raw -Encoding UTF8
# split on two or more newlines and dispose of empty blocks
$content -split '(\r?\n){2,}' | Where-Object { $_ -match '\S' } | ForEach-Object {
# trim the text block, split on newline and remove the trailing commas (or dots)
# output these joined with a comma
($_.Trim() -split '\r?\n' ).TrimEnd(",.") -join ','
} | Set-Content -Path 'Path\To\The\NEW_file.txt' -Encoding UTF8
Output:
name,surname,address
name,surname,address
all your terms ends with a , so you could use regex:
$content= "C:\test.txt"
$result= "path to the result file"
$CR = "`r`n"
$lines = Get-Content -Encoding UTF8 $content -raw
$option = [System.Text.RegularExpressions.RegexOptions]::Singleline
$lines = [regex]::new(',(?:\r?\n){2,}', $option).Replace($lines, $CR + $CR)
$lines = [regex]::new(',\r?\n', $option).Replace($lines, ",")
$lines | Out-File -FilePath $result -Encoding utf8
result:
name,surname,address
name1,surname,address
name,surname,address
name,surname,address
Below piece of code will give the required result.
$content= "Your file path"
$resultPath = "result file path"
Get-Content $content | foreach {
$data = $_
if($data -eq "address,")
{
$NewData = $data -replace ',',''
$data = $NewData + "`r`n"
}
$out = $out + $data
}
$out | Out-File $resultPath

How to replace string with quotes and brackets in file using Powershell

How I can replace string which contains quotes and brackets in a file using powershell ?
I have file with settings c:\app\settings.js
app_set("safe.mode", true);
app_set("api.uri", "https://apiurl.com");
app_set("api.version", 1);
And script ChangeSettins.ps1 but it actually doesn't change strings in a file.
$SettingsFile = c:\app\settings.js
$SAFEMODE = 'app_set("safe.mode", true);'
$APIURI = 'app_set("api.uri", "https://apiurl.com");'
$APIVERSION = 'app_set("api.version", 1);'
$SAFEMODE_PROFILE = Get-Content $SettingsFile | Select-String -Pattern "safe.mode"
#$SAFEMODE_PROFILE
$APIURI_PROFILE = Get-Content $SettingsFile | Select-String -Pattern "api.uri"
#$APIURI_PROFILE
$APIVERSION_PROFILE = Get-Content $SettingsFile | Select-String -Pattern "api.version"
#$APIVERSION_PROFILE
If ("$SAFEMODE_PROFILE" -eq "$SAFEMODE") {
Write-Host "safe mode is enabled"
}
Else {
Write-Host "enabling safe mode"
(Get-Content $SettingsFile) | Foreach-Object { $_ -Replace "$SAFEMODE_PROFILE", "$SAFEMODE" } | Set-Content $SettingsFile
}
If ("$APIURI_PROFILE" -eq "$APIURI") {
Write-Host "uri is correct"
}
Else {
Write-Host "updating uri"
(Get-Content $SettingsFile) | Foreach-Object { $_ -Replace "$APIURI_PROFILE", "$APIURI" } | Set-Content $SettingsFile
}
If ("$APIVERSION_PROFILE" -eq "$APIVERSION") {
Write-Host "api version is 1"
}
Else {
Write-Host "changing api version to 1"
(Get-Content $SettingsFile) | Foreach-Object { $_ -Replace "$APIVERSION_PROFILE", "$APIVERSION" } | Set-Content $SettingsFile
}
Replacement Operator
The -replace operator replaces all or part of a value with the
specified value using regular expressions.
Apply the Regex.Escape(String) Method where necessary, e.g. as follows:
$_ -Replace [regex]::Escape("$APIURI_PROFILE"), "$APIURI"

Writing a log bespoke log reader in PowerShell

I am trying to create a log reader. The data looks like so:
2017-11-27 13:24:41,791 [8] INFO CTSipEndpoint.CLogger.provider.gsiplib [(null)] - -00001 [Info] Info | 4744 | REGISTERdialog[1] 2-e:5;t:1-3 (dn:85188)
2017-11-27 13:24:41,791 [8] INFO CTSipEndpoint.CLogger.provider.gsiplib [(null)] - -00001 [Info] Info | 4744 | REGISTERdialog[1] event 2 REG/accepted
I am trying to do the following:
Return only lines in the last 48 hours to query further.
From above return any lines that contain the following phrases: "error"
"device","does not exist", "Could not identify speaker!","warn"
So far i have only been able to get this to work in an inefficient way, which runs against the file for each phrase and appends an array. Unfortunately this means that the date time becomes non-sequential. I need to now sort the content object at the end of the script to it be in sequence, or find a way to run this query smarter. Here is my script for reference:
$logfile = "C:\users\test\desktop\programlogs.log"
$content = ""
cat $logfile |
Select-String "ERROR" -SimpleMatch |
select -expand line |
foreach {
$_ -match '(.+)\s\[(ERROR)\]\s(.+)'| Out-Null
$error_time = [datetime]($matches[1]).split(",")[0]
if ($error_time -gt (Get-Date).AddDays(-2)) {
$content += $_ + "`n"
}
}
cat $logfile |
Select-String "device" -SimpleMatch |
select -expand line |
foreach {
$_ -match '(.+)\s\[(device)\]\s(.+)'| Out-Null
$error_time = [datetime]($matches[1]).split(",")[0]
if ($error_time -gt (Get-Date).AddDays(-2)) {
$content += $_ + "`n"
}
}
cat $logfile |
Select-String "does not exist" -SimpleMatch |
select -expand line |
foreach {
$_ -match '(.+)\s\[(does not exist)\]\s(.+)'| Out-Null
$error_time = [datetime]($matches[1]).split(",")[0]
if ($error_time -gt (Get-Date).AddDays(-2)) {
$content += $_ + "`n"
}
}
cat $logfile |
Select-String "Could not identify speaker!" -SimpleMatch |
select -expand line |
foreach {
$_ -match '(.+)\s\[(Could not identify speaker!)\]\s(.+)'| Out-Null
$error_time = [datetime]($matches[1]).split(",")[0]
if ($error_time -gt (Get-Date).AddDays(-2)) {
$content += $_ + "`n"
}
}
cat $logfile |
Select-String "Warn" -SimpleMatch |
select -expand line |
foreach {
$_ -match '(.+)\s\[(Warn)\]\s(.+)'| Out-Null
$error_time = [datetime]($matches[1]).split(",")[0]
if ($error_time -gt (Get-Date).AddDays(-2)) {
$content += $_ + "`n"
}
}
$content = $content | select -uniq
$file = "c:\temp\shortenedlog.txt"
$content| Add-Content -Path $file
Here's a short take, let me know if this helps or if needs tweaking:
$newlog=#()
$logfile = get-content C:\temp\programlogs.log
$searchFor="error","device","does not exist","Could not identify speaker!","warn"
foreach($line in $logfile){
if($line.Length -gt 18){
$datetime=date $line.substring(0,$line.indexof(","))
if(((date)-$datetime).TotalHours -lt 49){
$keep=$false
foreach($item in $searchFor){
if($line.contains($item)){ $keep=$true }
}
if ($keep){$newlog+=$line}
}
}
}
$newlog | sort | % {add-content C:\temp\NewLog.log $_}
Came up with a solution which I have fed in the days i am interested in, followed by the search criteria. Used this solution as works quickly.
#Set parameters.
$File = "c:\temp\RefinedLogs.txt"
$DateParam = (Get-Date).AddDays(-1).ToString('yyyy-MM-dd')
$DateParam1 = (Get-Date).ToString('yyyy-MM-dd')
$SearchForDate = #("$dateparam", "$dateparam1")
$SearchFor=#("error","device","does not exist","Could not identify speaker!","warn")
#Filter file with dates set in $SearchForDate.
$DateFiltered = Get-Content '.\MyAPP.log' | Select-String -Pattern $SearchForDate -SimpleMatch
#Filter variable for phrases set in $SearchFor.
$Content = $DateFiltered | Select-String -Pattern $SearchFor -SimpleMatch
#Make results readable
ForEach($line in $content){
$Object = "$line" + "`n"
$FinalResult += $Object
}
#Output results.
write-host $FinalResult

Load files using a table of contents in Powershell

I'm using the following code to load SQL scripts from a folder and execute them.
foreach ($sqlScript in Get-ChildItem -path "$pathToScripts" -Filter *.sql | sort-object) {
Write-Host "Running Script " $sqlScript.Name
#Execute the query
switch ($removeComments) {
$true {
(Get-Content $sqlScript.FullName -Encoding UTF8 | Out-String) -replace '(?s)/\*.*?\*/', " " -split '\r?\ngo\r?\n' -notmatch '^\s*$' |
ForEach-Object { $SqlCmd.CommandText = $_.Trim(); $reader = $SqlCmd.ExecuteNonQuery() }
}
$false {
(Get-Content $sqlScript.FullName -Encoding UTF8 | Out-String) -split '\r?\ngo\r?\n' |
ForEach-Object { $SqlCmd.CommandText = $_.Trim(); $reader = $SqlCmd.ExecuteNonQuery() }
}
}
}
I've been asked if its possible to have some sort of table of contents to execute these files in a particular sequence without having to rename them. Is it possible to have a comma delimited file that I could loop through and load each file in the same sequence?
Edit
This is the code I think I'm going to go with:
Get-Content $executionOrder
ForEach ($file in $executionOrder) {
$sqlScript = $pathToScripts + "\" + $file
Write-Host "Running Script " $sqlScript.Name
#Execute the query
switch ($removeComments) {
$true {
(Get-Content $sqlScript -Encoding UTF8 | Out-String) -replace '(?s)/\*.*?\*/', " " -split '\r?\ngo\r?\n' -notmatch '^\s*$' |
ForEach-Object { $SqlCmd.CommandText = $_.Trim(); $reader = $SqlCmd.ExecuteNonQuery() }
}
$false {
(Get-Content $sqlScript -Encoding UTF8 | Out-String) -split '\r?\ngo\r?\n' |
ForEach-Object { $SqlCmd.CommandText = $_.Trim(); $reader = $SqlCmd.ExecuteNonQuery() }
}
}
}
Is it possible to have a comma delimited file that I could loop through and load each file in the same sequence
Yes. You just need to update your outer look logic to account for that input. With only minor changes you can get what you want.
foreach ($sqlScript in (Import-CSV $pathtoCSV)){
# Process file.
}
That would work if you wanted a CSV file input as you requested. In comments it looks like you are getting a static list of file names in a predefined directory.
$pathToFileList = "C:\Bagel.txt"
$rootScriptDirectory = "\\path\to\scripts"
$removeComments = $true
Get-Content $pathToFileList | ForEach-Object{
# Build the full file paths
$scriptFilePath = [io.path]::Combine($rootScriptDirectory,$_)
# If this file actually exists then it should be processed
If(Test-Path $scriptFilePath -PathType Leaf){
# Get the file contents
$fileContents = Get-Content $scriptFilePath -Encoding UTF8 | Out-String
# Clean the file contents as required
if($removeComments){
$queries = $fileContents -replace '(?s)/\*.*?\*/', " " -split '\r?\ngo\r?\n' -notmatch '^\s*$'
} else {
$queries = $fileContents -split '\r?\ngo\r?\n'
}
# Execute each query of the file
$queries | ForEach-Object{
$SqlCmd.CommandText = $_.Trim()
$reader = $SqlCmd.ExecuteNonQuery()
}
# Hilarity ensues
} else {
Write-Warning "Could not locate the file '$scriptFilePath'"
}
}
The features of switch are a little wasted here since you only have two states. Move the things that actually get changes into an if block. Get the file list and test that the file exists. Open it and parse the queries from it with your already set logic.

Powershell issues out-file

I am trying to search a text file for a certain text then output that text to a different text file only if it matches. I'm having troubles creating this. I attached the code I have, but the issue is no matter what it is creating a results.txt file and the file is blank. I only want the results.txt file to be created if the multiplatform_201604110718.txt has CCTK STATUS CODE : SUCCESS inside it.
$Path = "C:\multiplatform_201604110718.txt"
$Text = "CCTK STATUS CODE : SUCCESS"
$PathArray = #()
$Results = "C:\results.txt"
# This code snippet gets all the files in $Path that end in “.txt”.
Get-ChildItem $Path -Filter “*.txt” |
Where-Object { $_.Attributes -ne “Directory”} |
ForEach-Object {
If (Get-Content $_.FullName | Select-String -Pattern $Text) {
$PathArray += $_.FullName
$PathArray += $_.FullName
}
}
Write-Host “Contents of ArrayPath:”
$PathArray | ForEach-Object {$_}
$PathArray | % {$_} | Out-File "C:\Resuts.txt"
If you really only need to check one file you can do it with much less code:
$Text = "CCTK STATUS CODE : SUCCESS"
$p = "C:\Users\kzbx\Desktop\test.txt"
if($ln = Select-String -pattern $text -path $p){
$ln.Line | Out-File C:\result.txt
}
This writes the line in which the text occurs to your result file (if i understood you correctly that is what you need, if not please clarify ;))