I'm working on a script that is based off of a cryptography script on blog.commandlinekungfu.com. Essentially I want to get the frequency of all of the letters in a text file. In the example, he uses Here-String to store the values, but I want to use Get-Content. Here's the breakdown.
This code works
PS c:\$foobar = #"
foo
bar
"#
PS c:\$foobar | Select-String -AllMatches "[A-Z]").matches
It returns the approriate values. However, if I have a text file that contains exactly the same information, I get a null value returned.
PS c:\$text = Get-Content "foobar.txt"
PS c:\$text | Select-String -AllMatches "[A-Z]").matches
Returns nothing
Does anyone know why a Here-String works but not Get-Content?
The here string is treated as one string, with get-content you pipe a collection of strings. You can pipe the filoe content to the Out-String cmdlet:
(get-content file.txt | out-string | Select-String -AllMatches "[A-Z]").matches
Related
Hello and thank you for your time. Here is what I am looking to do. I have several log files that I need to search through. I do this by using Get-ChildItem -Path C:\mylogfiles\*.log | Select-String -Pattern 'MyTextHere' However, now I want to complicate my life and only select text that is between single quotes in the log files.
Here is a sample of my log file:
This is some sample text in my log file. It has a lot of garbage that I don't want to see. However, it has text that I want to find, and if found I would like it to save just the selected text to a CSV file. I want to copy everything that is between single quotes. Here comes the text 'Please copy this text that is between the single quotes'
Any idea how I would go about doing this?
The following combines Select-String with ForEach-Object to extract only the phrases of interest (the parts of the line that matched the regex), wraps them in a [pscustomobject] instance with a .Phrase property and exports the results with Export-Csv:
Select-String -Path C:\mylogfiles\*.log -AllMatches -Pattern "'.*?'" |
ForEach-Object {
foreach ($phrase in $_.Matches.Value) {
[pscustomobject] #{ Phrase = $phrase.Trim("'") }
}
} |
Export-Csv -NoTypeInformation -Encoding utf8 result.csv
Note: If there can only ever be at most one phrase of interest per line, you can omit the -AllMatches switch and replace the ForEach-Object call with the following Select-String call, which uses a calculated property:
# ... |
Select-Object -Property #{ Name='Phrase'; Expression={ $_.Matches.Value.Trim("'") } } |
# ...
I'm trying to replace some specific parts of a selected string but am only returning the length property. Here's my code:
Get-ChildItem "StartPath/Something/Files" -Recurse -File | Select "FullName | Foreach {$_.FullName -replace "StartPath",""} | Export-Csv "ResultPath.csv"
If I omit the foreach bit, this works in that it spits out the full path. I'd like to trim the full path as I'm iterating over tons of files. I'm trying to replace a bit of the path in the beginning of the string but my code above just spits out a CSV file with just string lengths.
Looks like:
"123"
"12"
"52"
and so forth.
The intended result would be a csv file with instead of:
StartPath/Something/Files1
StartPath/Something/Files2
I'd have
Something/Files1
Something/Files2
I've tried a number of things and can't seem to figure it out. Any help is appreciated.
If you pass a string to select / Select-Object (to its positionally implied -Property parameter), it must be a property name.[1]
If you want to perform open-ended operations and/or produce open-ended output for each input object, you must use the ForEach-Object cmdlet:
Get-ChildItem "StartPath/Something/Files" -Recurse -File |
ForEach-Object {
[pscustomobject] #{ FullName = $_.FullName -replace 'StartPath' }
} |
Export-Csv "ResultPath.csv"
Note the use of a [pscustomobject] wrapper that defines a FullName property, so that Export-Csv creates a CSV with that property as its (only) column.
If you pipe [string] instances directly to Export-Csv, their properties are serialized to the output file - and a [string]'s only (public) property is its length (.Length), which is what you saw.
[1] There's also a way to create properties dynamically, using so-called calculated properties, which are defined via hash tables.
I am using powershell to filter a textfile using a regular expression. To do that I am using the following command:
Select-String -Pattern "^[0-9]{2}[A-Z]{2}[a-z]{5}" -CaseSensitive rockyou.txt > filter.txt
The issue however, when writing them to filter.txt it's preceding the matched strings with the name of the original file followed by the line numbers e.g.:
rockyou.txt:12345:abcdefg
rockyou.txt:12345:abcdefg
rockyou.txt:12345:abcdefg
How can I make it so that it ommits the line numbers?
Select-String outputs an object per match, and each has a Line property containing the original line in which the match occurred. You can grab only the Line value, like so:
... |Select-String ... |Select-Object -ExpandProperty Line |Out-File filter.txt
This way seems to work. Set-content saves the string version of the matchinfo object without any extra blank lines, as opposed to out-file or ">".
get-content rockyou.txt | select-string '^[0-9]{2}[A-Z]{2}[a-z]{5}' -ca |
set-content filter.txt
get-content filter.txt
01ABcdefg
It occurred to me you might still want the filename:
select-string '^[0-9]{2}[A-Z]{2}[a-z]{5}' rockyou.txt -ca |
% { $_.filename + ':' + $_.line } > filter.txt
cat filter.txt
rockyou.txt:01ABcdefg
I am trying to get the string value in csv file.
$path = "product.csv"
Get-Content $path | Select-String -AllMatches -Pattern "[^\x00-\x79]"
I successfully grab the string, however I wish display the line numbers then the string values.
Example Output:
LineNo String
1 a
2 b
3 c
I did successfully grab the linenumber using below command. How should I combine the command with the first command so the output will be alike the example output?
Get-Content $path | Select-String -AllMatches -Pattern "[^\x00-\x79]" | Select-Object LineNumber
If you want the entire line, select the Line property:
... |Select-Object LineNumber,Line
If you only want the part of the line that was matched by the pattern, you'll need a calculated property to grab the Value from the Matches property:
... |Select-Object LineNumber,#{Name='String';Expression={$_.Matches.Value}}
I have a script that reads series of log files located in different places and looks for an error code with Select-String. After the error code I print out the next four lines to a file with "-Context". That file's content gets dumped into an email and sent off.
$logsToCheck = "F:\Log1.log",
"F:\log2.log",
"F:\log3.log"
$logsToCheck | % {Select-String -Path $_ -Pattern "SQLCODE:2627" -Context
0, 4} | Out-File $dupChkFile
$emailbody = Get-Content $dupChkFile | ConvertTo-Html
The actual output of the string is poorly formatted and runs together. Is there a way to add blank lines or spaces after the last line when using Select-String -Context?
Originally I was piping the $emailbody to a Out-String but changed it to HTML to try to clear up formatting.
try reading out the match and context separately.
Select-String -Path $_ "SQLCODE:2627" -Context 0,2 | %{
$_.Line
$_.Context.PostContext
"-----Separator-----"
}
the default output of Select-String with Context is human-readable modified, this will return everything as an array of unmodified strings, so you can be sure there will always be newlines, and it will behave better with other cmdlt's including Out-String or loops.
I would suggest using concatenation:
% { "$(Select-String -Path $_ -Pattern 'SQLCODE:2627' -Context 0, 4)`r`n" } |
Out-File $dupChkFile -Append