getting specific part from line using powershell - powershell

I am trying to find specific lines in files. When I get a match using Select-String I do not want the entire line, I just want one specific part from the line (error part).
Is there a parameter I can use to do this?
For example:
If I did
select-string USERINTERACTION file.txt
and the file contained a line with:
MainControlInterleaf-D: 21:59:14:631: myErrorShowTracer (300) -> Info:: USERINTERACTION: <this is the error part> from type <1> occured
I'd like to get a result of just instead of the entire line getting returned.
EDIT:
One more thing I forgot: if there are differences between the lines, what do i need to change in the code?
For example:
log-29-10-2013_00-11-52.txt:2737:MainControlInterleaf-D: 02:50:50:097: myErrorShowTracer (300) -> Info:: USERINTERACTION: <this is the error1> from type <1> occured
log-29-10-2013_00-11-52.txt:2732:MainControlInterleaf-D: 02:50:39:933: myErrorQuitTracer (350) -> Info:: USERINTERACTION <this is the error2<br> OK ... try again.<br>

Unless file.txt is a really big file, this should work:'
$regex = '.+USERINTERACTION: (.+) from type <1> occured'
(get-content file.txt) -match $regex -replace $regex,'$1'

How about
Select-String -Pattern foo -Path X:\myfile.txt

Select-String outputs a MatchInfo object, you want to use something like this:
Select-String 'USERINTERACTION:\s*(.*?occured)' file.txt | Foreach {$_.matches.groups[1].value}

You are trying to return specific results, but do not provide the script with specific criteria.
Try RegEx matching (remember that you can use pipes in RegEx to form logical OR gates and deal with diffferent patterns that way).
Here's a fairly decent starting point for getting into this kind of solution, if you are unaccustomed to RegEx in POSH (or at all).

Related

Select-String - find a string that spans multiple lines

I am trying to read lines in a file and search for a pattern that spans two lines. Looking at the file in notepad++ I see a LF char in the file.
Example log.txt:
I want to find this
value here: OK
My simple code does not work and returns nothing:
select-string -Path "log.txt" -Pattern "find this\n*value here: OK"
I have tried many combos of various things here including .+ and \r that I found posted on various threads. I can get the first line by using:
select-string -Path "log.txt" -Pattern "find this\n*"
Result of above is: I want to find this
Adding anything more to the line above results in nothing being returned. Any ideas how to do this using select-string? I was trying to avoid using get content due to the potential size of the files I am working with.
So I think I understand your question. If you have a file that has a line that you want to key off of then the next line is the line that you want to look at:
(Select-String -Path "Log.txt" -Pattern "find this" -Context 1).Context.PostContext
I wasn't sure if that carriage return was an artifact of your formatting or not. If it is not then this would work better:
(Select-String -Path "Log.txt" -Pattern "find this" -Context 2).Context.PostContext[1]
Here is a way to do it if you don't know how many lines will be between the two bits:
$file = Get-Content 'Log.txt' -Raw
$file -match '(?smi)I want to find this.*(value here: OK)'
$matches[1]
Since you might want a multi line regex solution you need to read in the text file as one string.
Using the test file:
Stfuf
Bagel
I want to find this
value here: OK
Things
I was able to get the result using a simple matching pattern that satisfies your example text.
(Get-Content -Raw c:\temp\test.txt | Select-String -Pattern "([\w ]+)\s*value here: OK").Matches.Groups[1].Value
regex101.com
Basically gets the text preceding invariant spaces, including newlines and the static text "value here: OK". Could be made better with positive look aheads but this seems to work fine.

Batch File to Find and Replace in text file using whole word only?

I am writing a script which at one point has to check in a text file and remove certain strings. So far I have this:
powershell -Command "(gc myFile.txt) -replace 'foo', 'bar' | Out-File -encoding ASCII myFile.txt"
The only problem is that that can find and replace but will not remove the line all together.
The second problem is that say I am removing the line that has Mark, it needs to not remove a line that has something like Markus.
I don't know if this is possible with the powershell interface?
Your current code will only replace foo with bar, this is what replace does.
Removing the whole line if it matches requires a different approach, almost backwards, as you can use notmatch to output any lines that do not match you filter - effectively removing them.
Also using regex word boundaries will then only match Mark but not Markus:
(Get-Content file.txt) | Where-Object {$_ -notmatch "\bMark\b"} | Set-Content file.txt

Search two different string patterns in one line

THE SCENARIO
I have a *.txt file containing 3 lines:
test-1234.htm
test-5678.htm
somefile.htm
I need a script which will find specific string patterns in that *.txt file.
Currently, following script will find all *.htm files in *.txt file and store results in specified results.log file.
dir *.txt | Select-String -pattern "\.htm$" |Select-Object -Expandproperty line | Out-File results.log -Encoding utf8 -Width 500
QUESTION
How to modify it, so it only finds all "test-****.htm" lines?
(Will only log lines containing "test-" and ".htm")
Change the pattern argument to test-\d*.htm
'\d' - "Matches any digit character (0-9)"
'*' - "Match or more of the preceding token"
so it will match any num of digits
if you want to match at least 4 digits you can use test-\d{4,}.htm
i would recommend playing with regex using this site: http://regexr.com/
Thank you all for the hints!
Ultimately I got it working with:
test-.{4,}\.htm$
This way I was able to also include in results lines with digits+characters (for example "test-a12c.htm") and lines where there was something before the key word "test" (for example "this is a test-13bg.htm".
# user1432893
The site you've provided helped me with this! THX!
# Dave Sexton
with ^ in argument it didn't work.

Pipes in replace causing line to be duplicated

I have a script that I need to replace a couple of lines in. The first replace is going fine but the second is wiping out my file and duplicating the line multiple times.
My code
(get-content $($sr)) -replace 'remoteapplicationname:s:SHAREDAPP',"remoteapplicationcmdline:s:$($sa)" | Out-File $($sr)
(get-content $($sr)) -replace 'remoteapplicationprogram:s:||SHAREDAPP',"remoteapplicationprogram:s:||$($sa)" | Out-File $($sr)
The first replace works perfectly. The second one is causing this:
remoteapplicationprogram:s:||stagaredrremoteapplicationprogram:s:||stagarederemoteapplicationprogram:s:||stagareddremoteapplicationprogram:s:||stagarediremoteapplicationprogram:s:||stagaredrremoteapplicationprogram:s:||stagarederemoteapplicationprogram:s:||stagaredcremoteapplicationprogram:s:||stagaredtremoteapplicationprogram:s:||stagaredcremoteapplicationprogram:s:||stagaredlremoteapplicationprogram:s:||stagarediremoteapplicationprogram:s:||stagaredpremoteapplicationprogram:s:||stagaredbremoteapplicationprogram:s:||stagaredoremoteapplicationprogram:s:||stagaredaremoteapplicationprogram:s:||stagaredrremoteapplicationprogram:s:||stagareddremoteapplicationprogram:s:||stagared:remoteapplicationprogram:s:||stagarediremoteapplicationprogram:s:||stagared:remoteapplicationprogram:s:||stagared1remoteapplicationprogram:s:||stagared
etc...
Is this because of the ||? If so, how do I get around it?
Thanks!
To begin with, you should be using slightly more meaningful names for your variables. Especially if you want someone else to be reviewing your code.
The gist of your issue is that -replace supports regexes (regular expressions), and you have regex control characters in your pattern string. Consider the following simple example, and notice everywhere the replacement string is found:
PS C:\Users\Matt> "ABCD" -replace "||", "bagel"
bagelAbagelBbagelCbagelDbagel
-replace is also an array operator, so it works on every line of the input file, which is nice. For simplicity's sake, if you are not using a regex, you should just consider using the string method .Replace(), but it is case-sensitive, so that might not be ideal. So let's escape those control characters in the easiest way possible:
$patternOne = [regex]::Escape('remoteapplicationname:s:SHAREDAPP')
$patternTwo = [regex]::Escape('remoteapplicationprogram:s:||SHAREDAPP')
(get-content $sr) -replace $patternOne, "remoteapplicationcmdline:s:$sa" | Out-File $($sr)
(get-content $sr) -replace $patternTwo, "remoteapplicationprogram:s:||$sa" | Out-File $($sr)
Now we get both patterns matched as you have them written. Run $patternTwo on the console to see what has changed to it! $patternOne, as written, has no regex control characters in it, but it does not hurt to use the escape method if you are just expecting simple matching.
Aside from the main issue pointed out, there is also some redundancy and misconception that can be addressed here. I presume you are updating a source file to replace all occurrences of those strings, yes? Well, you don't need to read the file in twice, given that you can chain -replace:
$patternOne = [regex]::Escape('remoteapplicationname:s:SHAREDAPP')
$patternTwo = [regex]::Escape('remoteapplicationprogram:s:||SHAREDAPP')
(get-content $sr) -replace $patternOne, "remoteapplicationcmdline:s:$sa" -replace $patternTwo, "remoteapplicationprogram:s:||$sa" |
Set-Content $sr
Perhaps that will do what you intended.
You might notice that I've removed the subexpressions operators ($(...)) around your variables. While they have their place, they don't need to be used here. They are only needed inside more complicated strings, like when you need to expand object properties or something.

Add quotes to each column in a CSV via Powershell

I am trying to create a Powershell script which wraps quotes around each columns of the file on export to CSV. However the Export-CSV applet only places these where they are needed, i.e. where the text has a space or similar within it.
I have tried to use the following to wrap the quotes on each line but it ends up wrapping three quotes on each column.
$r.SURNAME = '"'+$r.SURNAME+'"';
Is anyone able to share how to forces these on each column of the file - so far I can just find info on stripping these out.
Thanks
Perhaps a better approach would be to simply convert to CSV (not export) and then a simple regex expression could add the quotes then pipe it out to file.
Assuming you are exporting the whole object $r:
$r | ConvertTo-Csv -NoTypeInformation `
| % { $_ -replace ',(.*?),',',"$1",' } `
| Select -Skip 1 | Set-Content C:\temp\file.csv
The Select -Skip 1 removes the header. If you want the header just take it out.
To clarify what the regex expression is doing:
Match: ,(.*?),
Explanation: This will match section of each line that has a comma followed by any number of characters (.*) without being greedy (? : basically means it will only match the minimum number of characters that is needed to complete the match) and the finally is ended with a comma. The parenthesis will hold everything between the two commas in a match variable to be used later in the replace.
Replace: ,"$1",
Explanation: The $1 holds the match between the two parenthesis mention above in the match. I am surrounding it with quotes and re-adding the commas since I matched on those as well they must be replaced or they are simply consumed. Please note, that while the match portion of the -replace can have double quotes without an issue, the replace section must be surrounded in single quotes or the $1 gets interpreted by PowerShell as a PowerShell variable and not a match variable.
You can also use the following code:
$r.SURNAME = "`"$($r.SURNAME)`""
I have cheated to get what I want by re-parsing the file through the following - guess that it acts as a simple find and replace on the file.
get-content C:\Data\Downloads\file2.csv
| foreach-object { $_ -replace '"""' ,'"'}
| set-content C:\Data\Downloads\file3.csv
Thanks for the help on this.