I'm reading a fixed-width file with 4000 rows though substrings, and assigning each substring to a header in a csv. But I'm not sure how to save the csv.
An example row am reading:
$line = ABC 7112123207/24/16Smith Timpson Head Coach 412-222-0000 00011848660 ELl CAAN HIGH SCHOOL 325 N Peal AVE. Smith Timpson Head Coach COLORADO CITY AZ 86021 01 FALL MALE 07/29/16EQ15031 1977904 BUDDY'S ALL STARS INC. BUDDY ALL STARS N V12V70R16 1.00V12V70R16
I've the csv with the headers.
$csvheaders = import-csv temp.csv
foreach ($Line in (Get-Content $FILE.FullName))
{
foreach($csh in $csvheaders)
{
$csh.GROUP = $line.Substring(0,10).Trim()
$csh.NUMBER = $line.Substring(10,8).Trim()
$csh.DATE=$line.Substring(18,8).Trim()
$csh.CONTACT_FIRST=$line.Substring(26,35).Trim()
$csh.CONTACT_LAST=$line.Substring(61,35).Trim()
}
}
I would need the csv output as:
Group Number Date Contact_First Contact_Last
ABC 71121232 07/24/16 Smith Timpson
There is a Export-Csv cmdlet:
Get-Content $FILE.FullName | ForEach-Object {
[PSCustomObject]#{
Group = $_.Substring(0,10).Trim()
Number = $_.Substring(10,8).Trim()
Date = $_.Substring(18,8).Trim()
Contact_First = $_.Substring(26,35).Trim()
Contact_Last = $_.Substring(61,35).Trim()
}
} | Export-Csv -Path 'Your_Output_Path.csv' -NoTypeInformation
Note: You probably need to specify a tab delimiter for the Export-Csv cmdlet.
Related
I have this table in normal string format ,
I want to convert this string to json object in PowerShell. ConvertTo-Json is not giving in correct format.
The answer depends somewhat on the true format of the table. If I assume this is tab delimited and that each column name doesn't have spaces I could pull it out something like:
$String =
#"
test test2 first others versions
------------------------------------------
Decimal 1 2 5 p
Decimal 1 3 8 p
Decimal 1 2 4 i
Decimal 2 2 6 p
Decimal 5 4 6 k
Decimal 2 5 2 p
"#
$String = $String -split "\r?\n"
$Headers = $String[0] -split "\s"
$Objects =
$String[2..($String.Count -1)] |
ConvertFrom-Csv -Header $Headers -Delimiter "`t" |
ConvertTo-Json
Above, -split the big string into lines, then look at the header line and -split it to get an array of column headers. Now skipping the first 2 elements in the $String array convert the remaining lines to objects using ConvertFrom-Csv and using the previously extracted $Headers array.
Note: This segment may also work and may be preferred for readability:
$Objects =
$String |
Select-Object -Skip 2 |
ConvertFrom-Csv -Header $Headers -Delimiter "`t" |
ConvertTo-Json
Note: Splitting on white space ( "\s" ) may cause issues if the field data may have whitespace itself.
However, given the ambiguity, a more certain approach might be more reliable, I would use the known start and end positions of the table's fields to do this.
Continuing with the above example string:
$String =
#"
test test2 first others versions
------------------------------------------
Decimal 1 2 5 p
Decimal 1 3 8 p
Decimal 1 2 4 i
Decimal 2 2 6 p
Decimal 5 4 6 k
Decimal 2 5 2 p
"#
$String = $String -Split "\r?\n"
$String |
Select-Object -Skip 2 |
ForEach-Object{
[PSCustomObject]#{
test = $_.SubString(0,7)
test2 = $_.SubString(8,1)
first = $_.SubString(14,1)
others = $_.SubString(20,1)
versions = $_.SubString(26,1)
}
}
Again, these positions may change depending if the columns are separated by spaces or tabs. My sample data may not be the same as yours and you may need to play with those positions. That said this is a very useful technique for deal with output from traditional console applications, very much worth knowing...
Note: Thanks Neko Nekoru; I added '?' to the RegEx to accommodate both Unix & Windows line ending styles.
I am trying to retrieve the running applications, the computers' username and its IP address. Now, every time that the results are saved on the text file, the IP address part would always give me this result:
"Length"
"11"
Is there any way to get the IP address?
$savepath = "C:\Users\$([Environment]::UserName)\Desktop\apps\runningapps.txt"
Get-Process | where {$_.mainwindowtitle.length -ne 0} |
select name, mainwindowtitle| ConvertTo-Csv -NoType |
Set-Content $savepath
Get-WmiObject -Class Win32_ComputerSystem | select username |
ConvertTo-Csv -NoType | Add-Content $savepath
Get-WmiObject Win32_NetworkAdapterConfiguration |
Where { $_.IPAddress } |
Select -Expand IPAddress |
Where { $_ -notlike "*:*" } | ConvertTo-Csv -NoType | Add-Content $savepath
The IP addresses are a list of strings, so you can write them directly to the output file if you want them one address per line:
Get-WmiObject Win32_NetworkAdapterConfiguration |
Where { $_.IPAddress } |
Select -Expand IPAddress |
Where { $_ -notlike "*:*" } | Add-Content $savepath
If you want the addresses as a comma separated list in one line you need to join them first:
(Get-WmiObject Win32_NetworkAdapterConfiguration |
Where { $_.IPAddress } |
Select -Expand IPAddress |
Where { $_ -notlike "*:*" }) -join ',' | Add-Content $savepath
ConvertTo-Csv won't help you here, because it takes an object as input and outputs a comma-separated list of the object's properties. If your input objects are strings (which have only the property Length) then the output becomes a list of the lengths of the input strings.
As a side note: a simpler way of building the output file path is to use the USERPROFILE environment variable:
$savepath = "$env:USERPROFILE\Desktop\apps\runningapps.txt"
I am trying to replace null values in a certain column to 0 using PowerShell.
I have the CSV in this format:
test test2 test3 test4
---- ----- ----- -----
blah fsds 4 45645
bla1 fsds1 45645
blah2 fsds2 4 34322
blah3 fsds3 4 67544
blah4 fsds4 3432432
so I want to go through the null values in "test3" and replace to 0.
I have this, but it doesn't work:
$inFilePath = "G:\powershell\excel\test.csv"
$csvColumnNames = (Get-Content $inFilePath | Select-Object -First 1).Split(",")
foreach ($row in $inFilePath) {
if ($row.test3 -eq $null) {
$row.test3 = 0
Write-Host "updating value in excel"
}
}
$csvColumnNames | Export-Csv "G:\powershell\excel\replaced2.csv" -NoTypeInformation
you are on the right track with foreach and if.Try this:
foreach($row in $inFilePath)
{
if (-not $row.test3)
{
$row.test3= 0
}
}
to get the column headers:
$inFilePath | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name
Use Import-Csv for reading and Export-Csv for writing CSV files.
$inFilePath = "G:\powershell\excel\test.csv"
$outFilePath = "G:\powershell\excel\replaced2.csv"
Import-Csv $inFilePath | % {
if (-not $_.test3) { $_.test3 = 0 }
$_ # echo all records, so they can be exported back to a file
} | Export-Csv $outFilePath -NoType
Powershell Script to Delete Blank Columns from CSV
I have a spread sheet which I'm importing into a MySQL database, the import fails because of blank columns in the spread sheet.
Is there a powershell script I can run / create that will check any given CSV file and remove blank columns?
Col1,Col2,Col3,Col4,,,,
Val1,Val2,Val3,Val4
How about something like this:
$x = Import-Csv YourFile.csv
$f = $x[0] | Get-Member -MemberType NoteProperty | Select name
$f | Add-Member -Name count -Type NoteProperty -Value 0
$f | %{
$n = $_.Name
$_.Count = #($x | Select $n -ExpandProperty $n | ? {$_ -ne ''}).count
}
$f = #($f | ? {$_.count -gt 0} | Select Name -expandproperty Name)
$x | Select $f | Export-Csv NewFile.csv -NoTypeInformation
It uses Get-Member to get the column names, cycles though each one to check how many are not blank and then uses the results in a select.
When I run Dave Sexton's code, I get:
Select-Object : Cannot convert System.Management.Automation.PSObject to one of the following
types {System.String, System.Management.Automation.ScriptBlock}.
At line:15 char:12
+ $x | Select <<<< $f | Export-Csv ColsRem.test.$time.csv -NoTypeInformation
+ CategoryInfo : InvalidArgument: (:) [Select-Object], NotSupportedException
+ FullyQualifiedErrorId :
DictionaryKeyUnknownType,Microsoft.PowerShell.Commands.SelectObjectCommand
I corrected this issue by adding one more line, to force each array element to be a string.
$x = Import-Csv YourFile.csv
$f = $x[0] | Get-Member -MemberType NoteProperty | Select name
$f | Add-Member -Name count -Type NoteProperty -Value 0
$f | %{
$n = $_.Name
$_.Count = #($x | Select $n -ExpandProperty $n | ? {$_ -ne ''}).count
}
$f = #($f | ? {$_.count -gt 0} | Select Name -expandproperty Name)
# I could get the select to work with strings separated by commas, but the array would
# always produce the error until I added the following line, explicitly changing the
#values to strings.
$f = $f | Foreach-Object { "$_" }
$x | Select $f | Export-Csv NewFile.csv -NoTypeInformation
My import CSV contains a few hundred columns and about half likely won't be populated, so getting rid of the extra columns was necessary. Now I just need to figure out how to counteract the unintended re-ordering of the columns into alphabetical order by name, without changing the names.
In my script I've collected all the data I want to report in different variables. Now I'm trying to generate an HTML-table so I can send this by mail.
What I would like to achieve is HTML-code that generates this:
OU | Logon scripts incorrect | Name incorrect | No description
\\Domain\NLD Users | 2 | 6 | 2
\\Domain\FRA users | 5 | 7 | 0
\\Domain\BEL users | 6 | 1 | 1
TOTAL USERS: 2048 | 13 | 14 | 3
I'm a bit confused on what would be the best approach for this (array, psobject, hashtable, ..). Because I'm not going to work with a foreach loop, the data would be static.
What I tried so far but isn't quite giving the desired result:
$Table = #( ('OU', 'Logon scripts incorrect', 'Name incorrect', 'No description'),
('\\Domain\NLD Users','2','6','2' ),
('\\Domain\FRA Users','5','7','0' ),
('\\Domain\BEL Users','6','1','1' ),
('TOTAL USERS: 2048','13','14','3' )
)
$Table | ConvertTo-Html -As Table -Fragment
It feels like I'm over-complicating things.
convertto-html is waiting for a psobject as its input.
What you can do is pass your data as csv then use convertfrom-csv to tansform it to psobject the run convertto-html :
$Table = #"
'\\Domain\NLD Users','2','6','2'
'\\Domain\FRA Users','5','7','0'
"#
$Table | ConvertFrom-Csv -Header 'OU', 'Logon scripts incorrect', 'Name incorrect', 'No description' | ConvertTo-Html -Fragment -As Table
#( ('OU', 'Logon scripts incorrect', 'Name incorrect', 'No description'),
('\\Domain\NLD Users','2','6','2' ),
('\\Domain\FRA Users','5','7','0' ),
('\\Domain\BEL Users','6','1','1' ),
('TOTAL USERS: 2048','13','14','3' )
) | Select-Object -Skip 1 | ForEach-Object{
[PSCustomObject]#{
OU = $_[0]
"Logon scripts incorrect" = $_[1]
"Name incorrect" = $_[2]
"No Description" = $_[3]
}
} | ConvertTo-Html -As Table -Fragment
From what i have read ConvertTo-Html takes .Net Objects and not arrays to convert to html. I converted your static table to a custom object which then was exported. This might look more to your liking.
You're creating an array of arrays with your statement, which looks neat, but isn't something ConvertTo-Html can handle. Create new objects instead (this is for v3):
$x = #(
([pscustomobject] #{
"OU" = "\\Domain\NLD Users";
"Logon scripts incorrect" = 2;
"Name incorrect" = 6;
"No description" = 2;
}),
([pscustomobject] #{
"OU" = "\\Domain\FRA Users";
"Logon scripts incorrect" = 5;
"Name incorrect" = 7;
"No description" = 0;
})
# ...and so on, or more realistically, constructed using Foreach-Object
)
$x | convertto-html -fragment
If you're confined to PowerShell v2, you can use new-object -type psobject -prop instead, but then the properties are not ordered so you will need an explicit Select.