Powershell -how to remove line details from selectstring output - powershell

I want to select a string "install status" from a log file by using powershell. For that i have used the command $status=selectstring -path $path -pattern "installstatus" .This cmd given an output installstatus=success with path and logtime and line details at beginning and i removed the path by adding |{$_.Line} after pattern in $status.And i want to remove line details also.how can i remove those details.I only want the pattern to be displayed .Any help will be apperciated.Thanks in advancd.
here the scenarios
$path="C:\Users\sumith\filename.log";
$status=select-string -path $path -pattern "Install_status"
output is
C:\Users\sumith\filename.log:79:ISS_LOG [14:45:41]: INSTALL_STATUS:SUCCESS
if i give
$status=select-string -path $path -pattern "Install_status" | {$_.Line}
the output will be
ISS_LOG [14:45:41]: INSTALL_STATUS:SUCCESS
now i want to remove ISS_LOG [14:45:41]: from output

IMO you are better of using a regular expression for this:
$File = ".\filename.log"
$Content = (Get-Content $File -raw)
$Pattern = [regex]'INSTALL_STATUS:\s*(\w+)'
"Using -Match operator"
if ($Content -Match $Pattern){
$Matches[0]
$Matches[1]
} Else {
"couldn#T find a match"
}
"Using [RegEx] .Matches method"
$Matches = $Pattern.Matches($Content)
$Matches.Captures[0].Value
$Matches.Captures.Groups[1].Value
Your question and comment differ in the file content,
a space following the colon INSTALL_STATUS: SUCCESS.
Sample output :
Using -Match operator
INSTALL_STATUS: SUCCESS
SUCCESS
Using [RegEx] .Matches method
INSTALL_STATUS: SUCCESS
SUCCESS

Try this,
$status=select-string -path $path -pattern "Install_status" | {$_.Line}
$status.Substring(19)OR
$status=select-string -path $path -pattern "Install_status" | {$_.Line}
$status.Substring($status.IndexOf('IN'))
or
$status=select-string -path $path -pattern "Install_status" | {$_.Line}
$status.Substring($status.IndexOf(']:')+2)
Or using Regex (Credits to LotPengs)
$Content=Get-Content D:\creditdetails.txt
$Pattern = [regex]'INSTALL_STATUS:\s*(\w+)'
if( $Pattern.Matches($Content) -ne $null){
$Matches=$Pattern.Matches($Content)
$Matches.Captures[0].Value
}else{
$Matches='No Match Found'
}
Assuming the log structure remains the same.

For console output (modified Chetan Kulkarni answer)
(Select-String -Path .\file.txt -Pattern 'abcde').line

Related

Powershell script to locate only files starting with specified letters and ending with .csv

cd 'A:\P\E\D'
$files = Get-ChildItem . *.CSV -rec
ForEach ($file in $files) {
(Get-Content $file -Raw) | ForEach-Object {
*some simple code*
} | Set-Content $file
}
How to modify this powershell script to locate only files starting with letters A/a to O/o and ending with .csv in specified directory cd?
I thought the solution below would work, but the test file M_K_O_X.CSV stored in the cd directory was not found and modified. The solution above will find and modify the file. It's possible that I have the regex expression wrong or the problem is somewhere else? I tried also this regex -- "[A-O]..CSV"
cd 'A:\P\E\D'
$files = Get-ChildItem . -rec | Where-Object { $_.Name -like "[a-oA-O]*.*.CSV" }
ForEach ($file in $files) {
(Get-Content $file -Raw) | ForEach-Object {
*some simple code*
} | Set-Content $file
}
Looking at your wildcard pattern, seems like you have an extra *. that shouldn't be there:
'M_K_O_X.CSV' -like '[a-oA-O]*.*.CSV' # False
'M_K_O_X.CSV' -like '[a-oA-O]*.CSV' # True
In this case you could simply use the -Include Parameter which supports character ranges. Also PowerShell is case insensitive by default, [a-oA-O]*.CSV can be reduced to [a-o]*.CSV:
Get-ChildItem 'A:\P\E\D' -Recurse -Include '[a-o]*.csv' | ForEach-Object {
($_ | Get-Content -Raw) | ForEach-Object {
# *some simple code*
} | Set-Content -LiteralPath $_.FullName
}
As commented, I would use the standard wildcard -Filter to filter for all files with a .csv extension.
Then pipe to a Where-Object clause in which you can use regex -match
$files = Get-ChildItem -Path 'A:\P\E\D' -Filter '*.csv' -File -Recurse |
Where-Object { $_.Name -match '^[a-o]' }
foreach ($file in $files) {
# switch `-Raw` makes Get-Content return a single multiline string, so no need for a loop
$content = Get-Content -Path $file.FullName -Raw
# *some simple code manipulating $content*
$content | Set-Content -Path $file.FullName
}
However, if these are valid csv files, I would not recommend using a pure textual manipulation on them, instead use Import-Csv -Path $file.FullName and work on the properties on each of the objects returned.

To check the file contents line by line

I need to check the contents line by line by selecting the string of the line.
I have declared each line matching string to a variable.Is it possible to use switch cases for looking into the variables
I have used if condition to check the each line with the help of variables .
I wanted to know whether we could use switch cases?
Consider file.txt having following contents :
$q = Get-Content -Path .\file.txt |Select-String 'Hello' -SimpleMatch
$w = Get-Content -Path .\file.txt |Select-String 'new' -SimpleMatch
$e = Get-Content -Path .\file.txt |Select-String 'World' -SimpleMatch
$r = Get-Content -Path .\file.txt |Select-String 'Hi' -SimpleMatch
$t = Get-Content -Path .\file.txt |Select-String 'greet' -SimpleMatch
So can we check the variables using the switch options. Is it possible to output the variables which are not present. How can we achieve the same if the file contents are large?
Can we use switch options and output the desired result?
If you just want to know which of the 5 words are not in any of the lines in the file, you can do this
$Pattern = 'Hello|new|World|Hi|greet'
$Test = (Get-Content -Path .\file.txt | Select-String -Pattern $Pattern -AllMatches).foreach{$_.matches.Value}
$($pattern -split '\|').where{$Test -notcontains $_}
But is that your goal?

Replace method used along-side Select-String not working

I am trying to search for the string, replace it and then output the file. I believe I have the syntax correct but for whatever reason it is not working. Can anyone spot why or is this even possible?
$DesiredTimeoutTime = '<Settings maxTimeout="04:00:00" />'
$path = "C:\Windows\Settings.log"
$currentTimeoutTime = Select-String -Path $path -SimpleMatch '<Settings maxTimeout=' -CaseSensitive
Write-Host $currentTimeoutTime
(Get-Content $path).Replace((Select-String -Path $path -SimpleMatch '<Settings maxTimeout="'), $DesiredTimeoutTime) | out-file $path
It finds the line and path but it is not saving the changes.
Thank you
You're overcomplicating things. Simply use the -replace operator with an appropriate regular expression:
$DesiredTimeoutTime = '04:00:00'
(Get-Content $path) -replace '(?<=<Settings maxTimeout=")[^"]*', $DesiredTimeoutTime |
Set-Content $path
(?<=...) is a positive lookbehind assertion, which basically means "look for something that is preceded by this pattern".

Powershell: addin line into the .txt file

I have a text (.txt) file with following content:
Car1
Car2
Car3
Car4
Car5
For changing Car1 for random text I used this script:
Get-ChildItem "C:\Users\boris.magdic\Desktop\q" -Filter *.TXT |
Foreach-Object{
$content = Get-Content $_.FullName
$content | ForEach-Object { $_ -replace "Car1", "random_text" } | Set-Content $_.FullName
}
This is working ok, but now I want to add one text line under Car2 in my text file.
How can I do that?
Just chain another -replace and use a new line!
Get-ChildItem "C:\Users\boris.magdic\Desktop\q" -Filter *.TXT |
Foreach-Object{
$file = $_.FullName
$content = Get-Content $file
$content | ForEach-Object { $_ -replace "Car1", "random_text" -replace "(Car2)","`$1`r`nOtherText" } | Set-Content $file
}
First thing is that | Set-Content $_.FullName would not work since the file object does not exist in that pipe. So one simple this to do it save the variable for use later in the pipe. You can also use the ForEach($file in (Get-ChildItem....)) construct.
The specific change to get what you want is the second -replace. We place what you want to match in brackets to that we can reference it in the replacement string with $1. We use a backtick to ensure PowerShell does not treat it as a variable.
We can remove some redundancy as well since -replace will work against the strings of file as a whole
Get-ChildItem "c:\temp" -Filter *.TXT |
Foreach-Object{
$file = $_.FullName
(Get-Content $file) -replace "Car1", "random_text" -replace "(Car2)","`$1`r`nOtherText" | Set-Content $file
}
While this does work with your sample text I want to point out that more complicated strings might require more finesse to ensure you make the correct changed and that the replacements we are using are regex based and do not need to be for this specific example.
.Replace()
So if you were just doing simple replacements then we can update your original logic.
Foreach-Object{
$file = $_.FullName
$content = Get-Content $_.FullName
$content | ForEach-Object { $_.replace("Car1", "random_text").replace("Car2","Car2`r`nOtherText")} | Set-Content $file
}
So that is just simple text replacement chained using the string method .Replace()

How can I look for file paths within .conf files?

There are a lot of directories and .conf/.xml files I have to open and search through. I have this right now:
$Path = "D:\Logs"
$Text = "*\log"
$PathArray = #()
$Results = "D:\Logs\Search.txt"
Get-Childitem $Path -Filter "*.conf" -Recurse |
Where-Object {$_.Attributes -ne "Directory"} |
ForEach-Object
{
If (Get-Content $_.FullName | Select-String -Pattern $Text -AllMatches)
{
$PathArray += $_.FullName
$PathArray += $_.FullName
}
}
Write-Host "Contents of ArrayPath:"
$PathArray | ForEach-Object {$_}
$PathArray | % {$_} | Out-File “D:\Logs\Search.txt”
I am trying to create this script, so I can have the out-file report all of the .conf files in a txt file with the correct path the .conf files are located in. I will also do the same with the .xml files by simply replacing the .conf with .xml. As of now, I am getting the .txt file up, but no paths. I know I am missing one or two things but I can not figure out what it is. I will have to manually change the old paths with the news ones I have already created. I would like to run this script to search for all the .conf/.xml files with a *\log or *\logs in them.
There's an issue with your regex not escaping backslash and it apparently not matching what you've shown as the typically content of a .conf file. Plus it can be simplified. Try this - adjusting the $Text regex to actually match the desired text in the .conf files:
$Path = "D:\Logs"
$Text = "\\log"
$Results = "D:\Logs\Search.txt"
$PathArray = #(Get-Childitem $Path -Filter *.conf -Recurse -File |
Where {(Get-Content $_.FullName -Raw) -match $Text})
Write-Host "Contents of ArrayPath:"
$PathArray
$PathArray | Out-File $Results -Encoding ascii
There were a couple of issues. Keith got the biggest one being that Select-String uses regex by default. Again, you had some redundancies like adding to the $pathArray twice and the use of ForEach-Object {$_}.
I wanted to show a solution that still uses select-string but uses some of the switch therein to get the use you want out of it. Main one being -simplematch which treats the pattern literally and not as regex. I saw an underscore leading the log in your sample text so I use that here. If you don't want to or it does not match your data simply remove it.
$Path = "D:\Logs"
$Text = "_log"
$Results = "D:\Logs\Search.txt"
$PathArray = Get-Childitem $Path -Filter "*.conf" -Recurse |
Where-Object {$_.Attributes -ne "Directory"} |
Where-Object{Select-string $_ -Pattern $Text -SimpleMatch -Quiet} |
Select-Object -ExpandProperty FullName
# Show results on screen
$PathArray
# Export results to file
$PathArray | Set-Content $Results