Reputation: 61
I have data in a text file like below, i want to read it value by value using powershell
Name Enabled Description
---- ------- -----------
administrator1 True
Azureuser True Built-in account for administering the computer/domain
DefaultAccount False A user account managed by the system.
Guest False Built-in account for guest access to the computer/domain
For example i want to read value for name in 2nd field. How can it be read?
Upvotes: 1
Views: 3814
Reputation: 17124
Parsing that kind of format is not easy, but here is an attempt:
$lineNo = 0
Get-Content .\test.txt | foreach {
# if first line, make a regex for parsing based on the headers
# (assumes header names have no spaces)
if ($lineNo -eq 0) {
$matches = [regex]::Matches($_, '\w+ +')
$headers = $matches | foreach {$_.Value.Trim()}
# build a regex based on column names & lengths
$regex = $(for($i = 0; $i -lt $matches.Count; $i++) {
if ($i -lt $matches.Count - 1) {
$quantifier = "{" + $matches[$i].Length + "}"
} else { $quantifier = "+" }
"(?<$($headers[$i])>.$quantifier)"
}) -join ""
}
# skip 2nd line and parse all others with the regex created before
elseif ($lineNo -gt 1) {
if ($_ -match $regex) {
[pscustomobject]$matches | select $headers
}
}
$lineNo++
# Now you can easily get the value you want
} | select Name
This will work properly for all 3 columns. Even with spaces in the values. (The script will break, if there are spaces in the header names, but this is usually not the case.)
Upvotes: 1
Reputation:
Best transform the text into an object with properties again.
This is quite easy as the 1st two columns don't have spaces in the values,
so this one liner:
gc .\file.txt|?{$_ -notmatch '^[ -]+$'}|%{$_.trim(' ') -split ' +',3 -join ','}|convertfrom-csv
yields this output:
Name Enabled Description
---- ------- -----------
administrator1 True
Azureuser True Built-in account for administering the computer/domain
DefaultAccount False A user account managed by the system.
Guest False Built-in account for guest access to the computer/domain
Looks familiar?
Yes, but stored in a variable i.e. $Data = ...,
allows you to directly acsess the 2nd Name (index is zero based) with
> $Data[1].Name
Azureuser
> $Data[2].Description
A user account managed by the system.
To better explain what the script does, here a dealiased version:
$Data = Get-Content .\file.txt | Where-Object {$_ -notmatch '^[ -]+$'} |
ForEach-Object{
$_.trim(' ') -split ' +',3 -join ','
} | ConvertFrom-Csv
Where-Object {$_ -notmatch '^[ -]+$'}
removes the line with only dashes and spaces
$_.trim(' ')
removes the trrailing spaces from the lines
-split ' +',3
splits the line at any number of spaces >1 into exactly 3 pieces
which are stuck together with -join ','
forming a valid csv file with a header
The final | ConvertFrom-Csv
does the work.
Upvotes: 1
Reputation: 574
It is difficult to convert it without having a delimiter in place. With a delimiter you could make use of ConvertFrom-String
If we would use ConvertFrom-String with this format, it will parse the first 2 columns correctly, but the description will be seperated in words.
((Get-Content .\test.txt) | ConvertFrom-String -PropertyNames Name, Enabled)
Result:
Name Enabled P3 P4
---- ------- -- --
Name Enabled Description
---- ------- -----------
administrator1 True
Azureuser True Built-in account
DefaultAccount False A user
Guest False Built-in account
To get the second result you have to take in account the header and separator line. This will return the full object.
((Get-Content .\test.txt) | ConvertFrom-String -PropertyNames Name, Enabled)[3]
Result:
Name : Azureuser
Enabled : True
P3 : Built-in
P4 : account
P5 : for
P6 : administering
P7 : the
P8 : computer/domain
This will only return the value from "Enabled"
(((Get-Content .\test.txt) | ConvertFrom-String -PropertyNames Name, Enabled)[3]).Enabled
Result:
True
Upvotes: 1
Reputation: 42143
For example i want to read value for name in 2nd field. How can it be read?
If I do not misunderstand, you want to read Azureuser
in the txt file, try the command below, $txt[3].Split()[0]
is what you want.
$txt = Get-Content 'C:\Users\joyw\Desktop\users.txt'
$txt[3].Split()[0]
Upvotes: 0