Get a line number on Powershell? - powershell

So I have been searching a lot and couldn't find anything that wouldn't return me nothing.
I have a code with a variable and I have a file with a lot of lines on it.
For example, I have the following file (things.txt):
Ketchup
Mustard
Pumpkin
Mustard
Ketchup
And what I want to take out is the line numbers of "Mustard". Here's the code I'm trying right now
$search="Mustard"
$linenumber=Get-Content things.txt | select-string $search -context 0,1
$linenumber.context
But it actually returns "". Everyone online was about using context but I only want to know the line number of every "Mustard" which are 2 and 4.
Thanks for your help!

Select-String returns the line number for you. You're just looking at the wrong property. Change your code to:
$search="Mustard"
$linenumber= Get-Content thing.txt | select-string $search
$linenumber.LineNumber

For people who are searching for one liner, code is self explanatory.
Get-Content .\myTextFile.txt | Select-String -Pattern "IamSearching" | Select-Object LineNumber
Edit(April 2022):
OR
(Select-String .\myTextFile.txt -Pattern "IamSearching").LineNumber

Try insert -Path after Get-Content

Related

Extract only the Pattern from Select-String

It's my first time using powershell and I'm a bit lost. I looked at the other answers on stackoverflow but I could not solve my problem.
I have a directory containing several files. These files each have a lot of lines. In these files I have to find the string ".MLB".
So I managed to build the following command :
Get-ChildItem -Path 'D:\Test\' -Include '*.txt' -Recurse | Select-String -Pattern 'MLB'
this seems to work. The problem is that it returns the whole line where my search appears which is very difficult to read.
I know that there is -Context to choose the number of line to display, but is it possible to do that with characters instead ? for example to display only the 20 characters that precede the pattern.
I've seen a few solution thanks to select-object but I have a really hard time to understand how to use it properly.
Thanks in advance.
EDIT: I made some progress. I tried the following:
Select-String -Path 'D:\TEST\log1.txt' -Pattern 'mlb' -AllMatches | ForEach-Object { $_.Matches.Value }
This returns the following
mlb mlb MLB mlb MLB
The only thing I need now would be a way to display what precede before that. Exemple:
data01a.mlb
data.mlb
DATE FILE MLB
HR.mlb
`

Powershell Select-String not finding what I expect

I am trying to parse file paths to just get the file name and I have a regex .*\
I'll use the following
Select-String -Pattern '.*\\' -InputObject $test -NotMatch
on a file path like C:\Users\User\Desktop\test.exe and it returns blank. If I remove the -NotMatch flag it returns the entire path. I tried using a regex tester so I know the regex is correct. What am I doing wrong?
Instead of using Select-String, use Split-Path -leaf.
Looks like -notmatch just ignores the whole line if there's a match. How about this? This is any number of characters that are not backslashes at the end of a line.
'C:\Users\User\Desktop\test.exe' | select-string [^\\]*$ | % matches | % value
test.exe

Removing blank lines from text file using batch

Recently this question was posted on stackoverflow, I have a similar problem as J. Williams except I only need to remove empty lines (removing spaces would not hurt the program though, it just isn't necessary). When I tried his original as well as the solution compo gave it only cleared the file instead of removing extra lines. I'm using it by itself in a batch file.
Example:
I need this:
Joe
Bob
Mark
Frank
Dutch
(blank line here too)
to become this:
Joe
Bob
Mark
Frank
Dutch
I'm open to attaching such a solution to this powershell script too, as it is what is giving me the blank lines: (Get-Content friends.txt) | Where-Object {$_ -notmatch "\bJoe\b"} | Set-Content friends.txt Thank's for your help.
This should work for you - in short, it reads all the lines of the file, then writes back only the lines with something in it to the file.
$friends = Get-Content friends.txt
$friends | Where-Object { $_ } | Set-Content friends.txt
If it's a relatively small file:
(Get-Content $infile) -match '\S' | Set-Content $infile
If it's too large to read into memory all at once:
Get-Content $infile -ReadCount 1000 |
ForeachObject {
$_ -match '\S' |
Add-Content $outfile
}
Another PowerShell method would be to use the Select-String cmdlet using the regex pattern .+ which means one or more of any character. Also if using Set-Content be sure to use the -NoNewLine parameter to prevent the unwanted blank line at the end. (Requires PS5+)
Select-String -Path C:\example.txt -Pattern '.+' |
Select-Object -ExpandProperty line |
Set-Content C:\exampleoutput.txt -NoNewline

Count specific string in text file using PowerShell

Is it possible to count specific strings in a file and save the value in a variable?
For me it would be the String "/export" (without quotes).
Here's one method:
$FileContent = Get-Content "YourFile.txt"
$Matches = Select-String -InputObject $FileContent -Pattern "/export" -AllMatches
$Matches.Matches.Count
Here's a way to do it.
$count = (get-content file1.txt | select-string -pattern "/export").length
As mentioned in comments, this will return the count of lines containing the pattern, so if any line has more than one instance of the pattern, the count won't be correct.
If you're searching in a large file (several gigabytes) that could have have millions of matches, you might run into memory problems. You can do something like this (inspired by a suggestion from NealWalters):
Select-String -Path YourFile.txt -Pattern '/export' -SimpleMatch | Measure-Object -Line
This is not perfect because
it counts the number of lines that contain the match, not the total number of matches.
it prints some headings along with the count, rather than putting just the count into a variable.
You can probably solve these if you need to. But at least you won't run out of memory.
grep -co vs grep -c
Both are useful and thanks for the "o" version. New one to me.

How to get files which have multiple required strings

I am trying to find the files which have given strings. I am using the below line
Get-ChildItem -recurse | Select-String -pattern "Magnet","Stew" | group path | select name
But it is giving the files which are having any one of the words "Magnet","Stew". But I want the files which have both the words. In logically speaking the above command interprets it as "Or" condition. I want "And" condition. Can anybody guide me of how to do this?
Try this for your regex:
'.*(?:stew.*magnet)|(?:magnet.*stew).*'
Edit:
If you're looking for those matches anywhere in the file:
Get-ChildItem -Recurse |
where {(
($_ | Select-String -Pattern 'Stew' -SimpleMatch -Quiet) -and
($_ | Select-String -Pattern 'Magnet' -SimpleMatch -Quiet)
)}
The solution posted at the link CB provided will work, but doesn't seem very efficient for what you're needing to do. The -SimpleMatch will be faster than using a Regex pattern, and the -Quiet switch will make it just return True or False, depending on whether it found a match in the file. If one or the other of the terms is much less likely to appear in the file, change the order so that one appears first in the test stack so the test will fail sooner and it can move on to the next file.