I would like to convert the content of this file (the first two columns, BARCODE and LOCATION) to object, but I am stuck creating the object..
#BARCODE LOCATION LIBRARY STATUS COPY
#------- -------- ------- ------ ----
#L40001L8 slot 41 DRP_TAPE_DRPLTO Full Primary_Global
#L40002L8 slot 96 DRP_TAPE_DRPLTO Full Primary_Global
#L40034L8 IEPort2 DRP_TAPE_DRPLTO Full Primary_Global
$object= #{}
ForEach ($i in $(gc "C:\temp\tapes.txt"))
{
$object.BARCODE= ($i.ToString().Substring(0,8))
$object.LOCATION= ($i.ToString().Substring(0,19))
New-Object psobject -Property $object
}
Can anyone help me?
Use creating object from hashtable:
$ht = #{ 'key1' = 'value1'; key2 = 'value2' }
$ht['key3'] = 'value3'
$o = [PSCustomObject]$ht
When you have fixed-width columns:
$lines = #(#'
#BARCODE LOCATION LIBRARY STATUS COPY
#------- -------- ------- ------ ----
#L40001L8 slot 41 DRP_TAPE_DRPLTO Full Primary_Global
#L40002L8 slot 96 DRP_TAPE_DRPLTO Full Primary_Global
#L40034L8 IEPort2 DRP_TAPE_DRPLTO Full Primary_Global
'# -split "`r`n" )
# $lines = [System.IO.File]::ReadAllLines($filePath)
$lines = $lines | Select-Object -Skip 2
$objects = $lines | % {
return [PSCustomObject]#{
BARCODE = $_.Substring(1,8).Trim()
LOCATION = $_.Substring(13,8).Trim()
}
}
$objects
First of all, The content of the file looks very much like you have started off with an array of objects, then 'stringyfied' that using Format-Table and copy/pasted the output from the console to your textfile.
Why every line is now commented by placing # in front, I don't know. Perhaps you did this to format the question in SO?
What I'm trying to say is that if that is indeed what happened, then it would make much more sense to change the script you used to create the file by removing the Format-Table from the code and saving the object array using a cmdlet like Export-Csv, or by saving as JSON or XML..
Anyway, if you have no choice in the matter and need to convert that file back to objects, you can do this:
# read the file line-by-line and replace the whitespaces with a comma
$data = switch -Regex -File 'D:\Test\File1.txt' {
'^#[^-]' { $_.TrimStart("#") -replace '\s+', ',' }
# if the comment marks '#' are NOT in the file, use this instead
# '^[^-]' { $_ -replace '\s+', ',' }
}
$result = $data | ConvertFrom-Csv | Select-Object BARCODE, LOCATION
# output on screen
$result
# output to CSV file
$result | Export-Csv -Path 'D:\Test\Output1.csv' -UseCulture -NoTypeInformation
Output on screen will look like
BARCODE LOCATION
------- --------
L40001L8 slot
L40002L8 slot
L40034L8 IEPort2
You can simply double-click the Output1.csv file to open in Excel
Related
I need to take a number such as:
59.234 and make it 00:59.234
and
1:01.555 01:01.555
I need to perform this on a column in a csv file.
If your input csv file looks anything like this:
"Something","Time","MoreStuff"
"whatever","59.234","whereever"
"etcetera","1:01.555","and so forth"
you can use below code to format the time values as you need them:
$csv = Import-Csv -Path 'D:\Test\thefile.csv'
$csv | ForEach-Object {
# get the field to format. in this demo it is $_.Time
$whole, $fraction = ($_.Time -replace '[:,]').PadLeft(8, '0') -split '\.'
# overwrite the field with the formatted time string
$_.Time = '{0}:{1}.{2}' -f $whole.Substring(0,2), $whole.Substring(2,2), $fraction.PadRight(3, '0')
}
# output on screen
$csv
# write to new file
$csv | Export-Csv -Path 'D:\Test\theNewfile.csv' -NoTypeInformation
Output on screen:
Something Time MoreStuff
--------- ---- ---------
whatever 00:59.234 whereever
etcetera 01:01.555 and so forth
This might not be graceful but it might work depending on how the format looks like if you have a smaller or larger number. Eg. 1:59.234 or just 23.
$CSV | select-object #{ Name = "MyTimeSpan"; Expression = { [System.TimeSpan]::Parse(("00:00:" + $_.ColumnName).Substring(("00:00:" + $_.ColumnName).Length - 12,12)) }}
in my script I want to read a csv-file into an array and split the text in the first column.
The file consists a table with 2 columns. In the first column there are the personal names with the short Usernames in brackets. In the second column are the position of the user.
User:
Hoch,Susane (HOCH05)
Albrecht, Melanie (ALBRE05)
Department:
Managment
Salesoffice
I read the first column in an array and want to split every char after the first "(". So the I have got "Hoch, Susanne" instead of "Hoch, Susane (HOCH05)".
I get the following error message:
[Selected.System.Management.Automation.PSCustomObject] contains no method with the name "Split".
The type of the variable "$value is:
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False PSCustomObject System.Object
I can´t find my misstake.
Here is my code:
$Arrayusername_ads_unique = New-Object System.Collections.ArrayList
$AD_User = New-Object System.Collections.ArrayList
$AD_User_table = New-Object System.Collections.ArrayList
$username_AD = New-Object System.Collections.ArrayList
$Arrayusername_ads_unique = Get-Content -Path "C:\temp\Userabgleich\Liste-original\User_ADS-utf8.csv"
$Arrayusername_ads_unique | Out-File C:\temp\Userabgleich\output-temp\User_ADS-utf8.csv -Append -Encoding utf8
$AD_User = Import-CSV 'C:\temp\Userabgleich\output-temp\User_ADS-utf8.csv' -Delimiter ";" | sort User
$AD_User_table = $AD_User | Select-Object User
foreach ($value in $AD_User_table)
{
$value.GetType()
$username_AD = $value.Split("(")
}
You can modify your foreach loop to achieve the results:
foreach ($value in $AD_User_table)
{
($value.user -split "\(")[0]
}
I am splitting on the .user property of $value to retrieve the value you are after in string format. By default, $value is going to be a [PSCustomObject] with a property called User. I am retrieving index 0 ([0]) because your -split match will consume a line of output whether or not you choose to keep the output.
If you are only looping to retrieve this particular result, you can accomplish this without a loop using regex substitution and named captures:
$ad_user_table.user -replace "(?<Name>.*?)\(.*",'${Name}'
since you did not provide a proper CSV to test against, i made a guess at what it would look like. [grin]
what it does ...
uses the .Split() method to split on the (
takes the 1st result of that split
trims away any leading/trailing whitespace
sends the result to the $Names collection
displays the content of that collection
here's the code ...
# fake reading in a CSV file
# in real life, use Import-CSV
$InStuff = #'
User,Department
"Hoch,Susane (HOCH05)","Managment"
"Albrecht, Melanie (ALBRE05)","Salesoffice"
'# | ConvertFrom-Csv
$Names = foreach ($IS_Item in $InStuff)
{
$IS_Item.User.Split('(')[0].Trim()
}
$Names
output ...
Hoch,Susane
Albrecht, Melanie
The powershell script:
$test = import-csv “C:\CSVFiles\test.csv”
ForEach ($item in $test)
{
$Name = $item.(“Name”)
$property = $item.("property")
$location = $item.(“location”)
Write-Output "$Name=$Name"
Write-Output "Property=$property"
Write-Output "Location=$location"
}
This script shows all the data for name,property and location for each row. I want the results to only show the data of one row;for example the row: n1;13;computer
The Cvs file =
Name;property;location
n1;13;computer
n2;65;computer
n3;12;tablet
n4;234;phone
n5;123;phone
n6;125;phone
What the current script spits out:
Name=n1
Property=13
Location=computer
Name=n2
Property=65
Location=computer
Name= n3
Property=12
Location=tablet
Name=n4
Property=234
Location=phone
Name=n5
Property=123
Location=phone
Name=n6
Property=125
Location=phone
There are many ways to select a Row of a csv and to present the data
For demonstration I use an inline csv with a here string.
$Test = #"
Name;property;location
n1;13;computer
n2;65;computer
n3;12;tablet
n4;234;phone
n5;123;phone
n6;125;phone
"# | ConvertFrom-Csv -delimiter ';'
> $test[0]
Name property location
---- -------- --------
n1 13 computer
> $test | where-object Name -eq 'n1'
Name property location
---- -------- --------
n1 13 computer
> $test | where-object Name -eq 'n1' | Select-Object Name,property
Name property
---- --------
n1 13
> $test | where-object Name -eq 'n1' | ForEach-Object {"Name:{0} has property: {1}" -f $_.Name,$_.property}
Name:n1 has property: 13
Once imported the csv rows contents are converted to objects
If you want to get the original row of the csv matching a criteria don't import but:
> Get-Content "C:\CSVFiles\test.csv" | Select-String '^n1'
n1;13;computer
^n1 is a regular expression anchoring the pattern at line begin.
Select-String -Path "C:\CSVFiles\test.csv" -Pattern '^n1'
Is the same without a pipe
So your current output is having 3 objects that are having 3 headers majorly.
One is Name; Second one is Property and the third one is Location.
As part of solution, you can either pull the records by specifying the index value or you can use the .Headername to pull all the sets of same object. Like:
Avoiding Foreach and accessing with $test[0] or $test[1]
Or you can use like: $test.Name directly to have all of the names from the csv
$dat = query user /server:$SERVER
this query gives below data
USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME
>vm82958 console 1 Active 1:28 2/9/2018 9:18 AM
adminhmc 2 Disc 1:28 2/13/2018 10:25 AM
nn82543 3 Disc 2:50 2/13/2018 3:07 PM
I would like to get each independent user details like STATE, USERNAME, ID details. I tried below code but it is not giving any data
foreach($proc in $dat) {
$proc.STATE # This is not working this command not giving any data.
$proc.ID # This is not working this command not giving any data.
}
Please help me on this.
The result of $dat.GetType() is:
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
This is very similar to this StackOverflow post, but you have blank fields in your data.
One solution is to deal with this first. Example below but this may break given data that is very different to your example. For a more robust and complete solution see Matt's comment
# replace 20 spaces or more with TWO commas, because it signifies a missing field
$dat2 = $dat.Trim() -replace '\s{20,}', ',,'
# replace 2 spaces or more with a single comma
$datTable = $dat2.Trim() -replace '\s{2,}', ',,'
foreach($proc in $datTable) {
$proc.STATE
$proc.ID
}
Another option is to use fixed Columns with string.Insert , like this:
$content = quser /server:$SERVER
$columns = 14,42,46,54,65 | Sort -Descending
$Delimiter = ','
$dat = $content | % {
$line = $_
$columns | % {
$line = $line.Insert($_, $Delimiter)
}
$line -replace '\s'
} |
ConvertFrom-Csv -Delimiter $Delimiter
And Then:
foreach($proc in $dat) {
$proc.STATE
$proc.ID # Will show the relevant Data
}
So I have a CSV file which I need to manipulate a bit, select the data I need and export to another CSV file.
The code I have is:
$rawCSV = "C:\Files\raw.csv"
$outputCSV = "C:\Files\output.csv"
Import-Csv -Header #("a","b","c","d") -Path $rawCSV |
select -Skip 7 |
Where-Object { $_.b.length -gt 1 } |
ft b,a,c,d |
Out-File $outputCSV
So this code uses the Import-Csv command to allow me to select just the columns I need, add some headers in the order I want and then I am simply putting the output in to a CSV file called $outputCSV. The contents of this output file look something like this:
b a c d
- - - -
john smith 29 England
mary poopins 79 Walton
I am not sure what the delimiter is in this output and rather than these columns being treated as individuals, they are treated as just one column. I have gone on further to replace all the spaces with a comma using the code:
$b = foreach ($line in $a)
{
$fields = $line -split '`n'
foreach ($field in $fields)
{
$field -replace " +",","
}
}
Which produces a file that looks like this:
b,a,c,d
john,smith,29,England
mary,poppins,79,Walton
But these are all still treated as one column instead of four separate columns as I need.
* UPDATE *
Using the answer given by #, I now get a file looking like this:
Don't use ft to reorder your columns - it's intended to format output for the screen, not really suitable for CSV.
"Manual" solution:
$rawCSV = "C:\Files\raw.csv"
$outputCSV = "C:\Files\output.csv"
# Import and filter your raw data
$RawData = Import-Csv -Header #("a","b","c","d") -Path $rawCSV
$Data = $RawData | Select -Skip 7 | Where-Object { $_.b.length -gt 1 }
# Write your headers to the output file
"b","a","c","d" -join ',' | Out-File $outputCSV -Force
$ReorderedData = foreach($Row in $Data){
# Reorder the columns in each row
'{0},{1},{2},{3}' -f $Row.b , $Row.a , $Row.c, $Row.d
}
# Write the reordered rows to the output file
$ReorderedData | Out-File $outputCSV -Append
Using Export-Csv:
As of PowerShell 3.0, you could also push the rows into a [pscustomobject] and pipe that to Export-Csv (pscustomobject preserves the order in which you supply the properties):
$rawCSV = "C:\Files\raw.csv"
$outputCSV = "C:\Files\output.csv"
# Import and filter your raw data
$RawData = Import-Csv -Header #("a","b","c","d") -Path $rawCSV
$Data = $RawData | Select -Skip 7 | Where-Object { $_.b.length -gt 1 }
# Take the columns you're interested in, put them into new custom objects and export to CSV
$Data | ForEach-Object {
[pscustomobject]#{ "b" = $_.b; "a" = $_.a; "c" = $_.c; "d" = $_.d }
} | Export-Csv -NoTypeInformation $outputCSV
Export-Csv will take care of enclosing strings in quotes to escape ',' properly (one thing less for you to worry about)
First of all, what your raw CSV file looks like? If it's already like this
john,smith,29,England
mary,poppins,79,Walton
then import-csv will give you an array of objects which you can easily manipulate (and objects are the main reason to use PowerShell ;). For example, to check what you have after import:
$r = Import-Csv -Path $rawCSV -Header #("b","a","c","d")
$r.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
$r[0] | get-member
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
a NoteProperty System.String a=smith
b NoteProperty System.String b=john
c NoteProperty System.String c=29
d NoteProperty System.String d=England
For now you have array of objects with properties named "a","b","c","d". To manipulate objects you have select-object cmdlet:
$r | Select-Object a,b,c,d
a b c d
- - - -
smith john 29 England
poppins mary 79 Walton
And after all use export-csv to set the output file:
$r | where { $_.b.length -gt 1 } |
select a,b,c,d |
Export-Csv -NoTypeInformation -Encoding utf8 -path $outputCSV
I could think of two possible reasons why your data teated as one column:
consuming application expect different encoding and can't find
delimiters
delimiters are not commas but something else