Getting character count for each row in text doc - powershell

I am trying to get the character count for each row in a text doc. The contents of my text doc are:
1
15
69
124
300
I've been trying variants of the PS script:
get-content c:\serverlist.txt | foreach-object {measure-object -character}
But the best I can get returned is:
Lines Words Characters Property
------- -------- -------------- -----------
0 0 0 0 0
Not sure what I'm missing here, but any help would be appreciated!
Thanks!

You have to pipe directly into Measure-Object:
Get-Content c:\serverlist.txt | Measure-Object -Character
Otherwise you'd have to do either
| ForEach-Object { $_ | Measure-Object -Character }
which would be a bit of weird use of the pipeline or
| ForEach-Object { Measure-Object -Character -InputObject $_ }
which would be just about the same as the variant above.

Related

how to count split words select-string pattern powershell. text file log life .txt .log

I need to count rows with values ms 2xx (where xx is any number) it can be 200,201,202,258,269 etc. (It has to start with number 2)
Then do it also with numbers 4 and 5.
There In my .txt file with rows like this:
2022.10.20 13:42:01.570 | INFO | Executed action "PERPIRestEPService.Controllers.PERPIController.GetVersion (PERPIRestEPService)" in 4.9487ms
2022.10.20 13:42:01.570 | INFO | Executed endpoint '"PERPIRestEPService.Controllers.PERPIController.GetVersion (PERPIRestEPService)"'
2022.10.20 13:42:01.570 | INFO | Request finished in 5.5701ms 200 application/json; charset=utf-8
2022.10.20 13:42:01.908 | DBUG | Starting HttpMessageHandler cleanup cycle with 4 items
2022.10.20 13:42:01.908 | DBUG | Ending HttpMessageHandler cleanup cycle after 0.0105ms - processed: 4 items - remaining: 0 items
2022.10.20 13:44:30.632 | DBUG | Received data from rabbit: <?xml version="1.0"?>
<TransactionJournal xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.datapac.sk/Posybe">
<Header>
<GeneratedDate>2022-10-20T13:44:30.5409065+02:00</GeneratedDate>
<BusinessDate>2022-10-20</BusinessDate>
<SourceSystem>Posybe MCFS</SourceSystem>
<Site>C702</Site>
<Version>1.0</Version>
I need to make this table. It should look like this:
Count Name
----- ----
97 200
278 202
2 205
18 275
I have this code:
$files = Get-ChildItem -Path "C:\Users\krivosik\Desktop\Scripts\logs\PosybeRestEPService\*.log"
#Write-Host $files
$files |
Select-String -Pattern 'ms 2','ms 4' |
Group-Object Pattern -NoElement
#| Select-Object Count, Name
foreach ($file in $files){
$mss=$file | Select-String -Pattern 'ms 2','ms 4'
foreach ($l in $mss){
$s = $l -split(" ")
$s[9]
$s[9] | Group-Object | Select-Object Count, Name
#Group-Object Pattern -NoElement |
#Select-String -Pattern 'ms 2','ms 4'
}
}
I tried to split the row and now I have just the numbers I want to. Now I have to count them and make that table but I dont know how. I should be using Group-object but It just does not work for me.
This is the only output I can get from this code:
Count Name
----- ----
1463 ms 2
1 ms 4
202
Count : 1
Name : 202
202
Count : 1
Name : 202
202
Count : 1
Name : 202
202
Count : 1
Name : 202
Group-Object is the right solution in this scenario. You just have to group by the value that was matched for the name, this way it accounts for the total count of how many were found with that pattern:
Select-String -Path 'C:\Users\krivosik\Desktop\Scripts\logs\PosybeRestEPService\*.log' -Pattern '(?<=\d.*?ms )(2|4|5)\d+' |
Group-Object -Property { $_.Matches.Value } -NoElement
As for the pattern matching, use a "positive lookbehind" to ensure the capture of what would be the name property, making it less error-prone in case something else down the line matches ms 2/4/5.
Postive LookBehind: (?<=\d.*?ms ), ensures this pattern matches before you can match what follows without actually capturing that match.
(2|4|5)\d+, here is the actual capture of the name property with options to match a pattern starting with either 2,4, or 5 only.
Now, Group-Object can take the output of Select-String and group them by the values matched via Matches.Value; i.e. 2xx,4xx,5xx.
Edit: The path on where these values are found is already exposed via Select-String but you have to bring it out using a calculated property. Also, if you want to match exact values of ms 2xx the regex following the positive lookbehind has to be changed to those values:
Select-String -Path 'C:\Users\krivosik\Desktop\Scripts\logs\PosybeRestEPService\*.log' -Pattern '(?<=\d.*?ms )(200|202)' |
Group-Object -Property { $_.Matches.Value } |
Select-Object -Property Count, Name, #{
Name = 'Path'
Expression = { $_.Group[0].Path }
}
The | is used as a delimiter for an "or" RegEx operator, so it will match exactly 200, or 202.
If you want to add more value to match exactly, just separated them by the | delimiter inside the ().

Get results of For-Each arrays and display in a table with column headers one line per results

I am trying to get a list of files and a count of the number of rows in each file displayed in a table consisting of two columns, Name and Lines.
I have tried using format table but I don't think the problem is with the format of the table and more to do with my results being separate results. See below
#Get a list of files in the filepath location
$files = Get-ChildItem $filepath
$files | ForEach-Object { $_ ; $_ | Get-Content | Measure-Object -Line} | Format-Table Name,Lines
Expected results
Name Lines
File A
9
File B
89
Actual Results
Name Lines
File A
9
File B
89
Another approach how to make a custom object like this: Using PowerShell's Calculated Properties:
$files | Select-Object -Property #{ N = 'Name' ; E = { $_.Name} },
#{ N = 'Lines'; E = { ($_ | Get-Content | Measure-Object -Line).Lines } }
Name Lines
---- -----
dotNetEnumClass.ps1 232
DotNetVersions.ps1 9
dotNETversionTable.ps1 64
Typically you would make a custom object like this, instead of outputting two different kinds of objects.
$files | ForEach-Object {
$lines = $_ | Get-Content | Measure-Object -Line
[pscustomobject]#{name = $_.name
lines = $lines.lines}
}
name lines
---- -----
rof.ps1 11
rof.ps1~ 7
wai.ps1 2
wai.ps1~ 1

Powershell to reformat the file content

I have a script which gets content from one file and checks for its ip. Then that is added to some other text file.
[System.Collections.ArrayList]$hlist1 = Get-Content -Path "C:\Timezone\Update\host.txt"
$hiplist = New-Object System.Collections.ArrayList
$hlist2 = New-Object System.Collections.ArrayList
ForEach ($h in $hlist1)
{
$hip = Resolve-DnsName $h
$hiplist.Add($hip)
}
$hiplist | Out-File "C:\Timezone\Update\hiplist.txt"
The file which is getting created is as shown below:
---- ---- --- ------- --------
WIN-JB2A2FS84MQ.domain.com A 1200 Answer 10.3.0.4
8
WIN-QP0BH4SD2H9.domain.com A 1200 Answer 10.3.1.1
9
I need to:
get rid of the first -------- lines.
get the entire ip in the same line (10.3.0.10)
Have tried Format-Table -Autosize, then Select -Skip 1 etc, but no luck.
How can this be achieved.? Please note that the code works fine as expected when it is ran manually, but throws this issue when executed using task scheduler.
Edit Based on Matt's answer
Now the text file contains:
"Address","IPAddress","QueryType","IP4Address","Name","Type","CharacterSet","Section","DataLength","TTL"
"10.3.0.48","10.3.0.48","A","10.3.0.48","WIN-JB2A2FS84MQ.domain.com","A","Unicode","Answer","4","1200"
"10.3.1.19","10.3.1.19","A","10.3.1.19","WIN-QP0BH4SD2H9.domain.com","A","Unicode","Answer","4","1200"
Peter-sal's reply output:
Name Type TTL Section IPAddress
---- ---- --- ------- ---------
WIN-JB2A2FS84MQ.domain.com A 1200 Answer 10.3.0.48
WIN-QP0BH4SD2H9.domain.com A 1200 Answer 10.3.1.19
But again on top of Name there's one space. I need to delete everything present before WIN-JB2.....
I cannot test perfectly but I would like to come back to an earlier comment of mine. Resolve-DNSName returns objects so their output is better destined for something object aware. Export-CSV should be preferable here.
$hlist1 = Get-Content -Path "C:\Timezone\Update\host.txt"
$hlist1 | ForEach-Object{Resolve-DnsName $_} |
Export-Csv "C:\Timezone\Update\hiplist.txt" -NoTypeInformation
I normally don't like this but if you prefer you should be able to use the Format-table output now. This seems to be more inline with what you are looking for.
$hlist1 = Get-Content -Path "C:\Timezone\Update\host.txt"
$hlist1 | ForEach-Object{Resolve-DnsName $_} |
Format-Table -HideTableHeaders | Select-Object -Skip 1 |
Out-File "C:\Timezone\Update\hiplist.txt" -Width 200
Perhaps you prefer that output. The header should be removed now as well as a blank line in the beginning.
That creates some white-space before and after the output. Simple solution is to wrap that up in a Trim()
$hlist1 = Get-Content -Path "C:\Timezone\Update\host.txt"
$results = ($hlist1 | ForEach-Object{Resolve-DnsName $_} |
Format-Table -HideTableHeaders |
Out-string).Trim()`
$results | Out-File "C:\Timezone\Update\hiplist.txt" -Width 200`

How do I get filename and line count per file using powershell

I have the following powershell script to count lines per file in a given directory:
dir -Include *.csv -Recurse | foreach{get-content $_ | measure-object -line}
This is giving me the following output:
Lines Words Characters Property
----- ----- ---------- --------
27
90
11
95
449
...
The counts-per-file is fine (I don't require words, characters, or property), but I don't know what filename the count is for.
The ideal output would be something like:
Filename Lines
-------- -----
Filename1.txt 27
Filename1.txt 90
Filename1.txt 11
Filename1.txt 95
Filename1.txt 449
...
How do I add the filename to the output?
try this:
dir -Include *.csv -Recurse |
% { $_ | select name, #{n="lines";e={
get-content $_ |
measure-object -line |
select -expa lines }
}
} | ft -AutoSize
I can offer another solution :
Get-ChildItem $testPath | % {
$_ | Select-Object -Property 'Name', #{
label = 'Lines'; expression = {
($_ | Get-Content).Length
}
}
}
I operate on the. TXT file, the return value is like this ↓
Name Lines
---- ----
1.txt 1
2.txt 2
3.txt 3
4.txt 4
5.txt 5
6.txt 6
7.txt 7
8.txt 8
9.txt 9
The reason why I want to sort like this is that I am rewriting a UNIX shell command (from The Pragmatic Programmer: Your Journey to Mastery on page 145).
The purpose of this command is to find out the five files with the largest number of lines.
At present, my progress is the above content,i'm close to success.
However, this command is far more complicated than the UNIX shell command!
I believe there should be a simpler way, I'm trying to find it.
find . -type f | xargs wc -l | sort -n | tail -5
I have used the following script that gives me lines in files of all sub directories in folder c:\temp\A. The output is in lines1.txt file. I have applied a filer to choose only file types of ".TXT".
Get-ChildItem c:\temp\A -recurse | where {$_.extension -eq ".txt"} | % {
$_ | Select-Object -Property 'Name', #{
label = 'Lines'; expression = {
($_ | Get-Content).Length
}
}
} | out-file C:\temp\lines1.txt

Count the comma in each line and show the line numbers in a text file

I'm using the following script to get the comma counts.
Get-Content .\myFile |
% { ($_ | Select-String `, -all).matches | measure | select count } |
group -Property count
It returns,
Count Name Group
----- ---- -----
131 85 {#{Count=85}, #{Count=85}, #{Count=85}, #{Count=85}...}
3 86 {#{Count=86}, #{Count=86}, #{Count=86}}
Can I show the line number in the Group column instead of #{Count=86}, ...?
The files will have a lot of lines and majority of the lines have the same comma. I want to group them so the output lines will be smaller
Can you use something like this?
$s = #"
this,is,a
test,,
with,
multiple, commas, to, count,
"#
#convert to string-array(like you normally have with multiline strings)
$s = $s -split "`n"
$s | Select-String `, -AllMatches | Select-Object LineNumber, #{n="Count"; e={$_.Matches.Count}} | Group-Object Count
Count Name Group
----- ---- -----
2 2 {#{LineNumber=1; Count=2}, #{LineNumber=2; Count=2}}
1 1 {#{LineNumber=3; Count=1}}
1 4 {#{LineNumber=4; Count=4}}
If you don't want the "count" property multiple times in the group, you need custom objects. Like this:
$s | Select-String `, -AllMatches | Select-Object LineNumber, #{n="Count"; e={$_.Matches.Count}} | Group-Object Count | % {
New-Object psobject -Property #{
"Count" = $_.Name
"LineNumbers" = ($_.Group | Select-Object -ExpandProperty LineNumber)
}
}
Output:
Count LineNumbers
----- -----------
2 {1, 2}
1 3
4 4