Before you begin ensure that Microsoft Windows PowerShell 3 or later is available. To view which version of PowerShell is installed, enter the following command in a PowerShell session:
PS C:\> $PSVersionTable.PSVersion
PS C:\> Get-Process -name powershell | fl -property name,id,starttime Name : powershell Id : 3980 StartTime : 29/03/2017 10:52:07
Extracting columns from text file using PowerShell
Get-Content test.txt | Foreach {($_ -split '\s+',4)[0..2]}
And if you want the data in those columns printed on the same line:
Get-Content test.txt | Foreach {"$(($_ -split '\s+',4)[0..2])"}
Note that this requires PowerShell 2.0 for the -split operator. Also, the ,4 tells the the split operator the maximum number of split strings you want but keep in mind the last string will always contain all extras concat'd.
For fixed width columns, here's one approach for column width equal to 7 ($w=7):
$res = Get-Content test.txt | Foreach { $i=0;$w=7;$c=0; ` while($i+$w -lt $_.length -and $c++ -lt 2) { $_.Substring($i,$w);$i=$i+$w-1}}
$res will contain each column for all rows. To set the max columns change $c++ -lt 2 from 2 to something else. There is probably a more elegant solution but don't have time right now to ponder it.
Thanks, but this doesn't seem to work. I'm running PowerShell 2 and try to extract first two columns from my fixed-width .dat file (text file)
The cut example you link to uses a space delimiter and grabs columns 1 thru 3. If this doesn't apply to your case, can you state what your requirements are? Sounds like fixed column width instead of delimited. If so, what is the column width?
My data is in fixed-width text file (spaces between). I modified your code and got this:
Get-Content text.txt | Foreach {"$($_.split()[0..2])"}
This gets me quite near, but this generates addition row breaks between rows.
Make sure $OFS is set to either $null or something like ' '. Also did you try $_ -split '\s+',3? That should get rid of the extra empty entries. The way string.split works is that each consecutive space after the first will result in an extra empty string resturned.
Assuming it's white space delimited this code should do.
$fileName = "someFilePath.txt" $columnToGet = 2 $columns = gc $fileName | %{ $_.Split(" ",[StringSplitOptions]"RemoveEmptyEntries")[$columnToGet] }
I tried this like C:> .\Extract_Two_Columns_From_Text_File.ps1 > twocols.dat But it did not print anything?
type foo.bar | % { $_.Split(" ") | select -first 3 }
If you have mulitple spaces between columns (quite common) this will produce a bunch of empty entries. This is why Jared uses the [StringSplitOptions]::RemoveEmptyEntries enum value.
This produces the same: Get-Content text.txt | Foreach {“$($_.split()[0..2])”}.
I tried also this: Get-Content text.txt | Foreach {“$($_.split(” “, [StringSplitOptions]::RemoveEmptyEntries))[0..2])”}, but it still produces those empty lines.
gc R:\test.txt | % { $_ -split '\s+',4 | select -f 3 }
How to select the first 10 columns of a headerless csv file using PowerShell?
I have a CSV file called test.csv ($testCSV). There are many columns in this file but I would simply like to select the first 10 columns and put these 10 columns in to another CSV file. Please note that I DO NOT HAVE ANY COLUMN HEADERS so can not select columns based on a column name.
The below line of code will get the first 10 ROWS of the file:
$first10Rows = Get-Content $testCSV | select -First 10
However I need all the data for the first 10 COLUMNS and I am struggling to find a solution.
I have also had a look at splitting the file and attempting to return the first column as follows:
$split = ( Get-Content $testCSV) -split ',' $FirstColumn = $split[0]
I had hoped the $split[0] would return the entire first column but it only returns the very first field in the file.
UPDATE
Import-Csv -Delimiter "," -Header @("a","b","c") -Path $testCSV | Select a,b
However I am now also trying to import the CSV file only where column b is not null by adding this extra bit of code:
Import-Csv -Delimiter "," -Header @("a","b","c") -Path $testCSV | Select a,b | where b -notmatch $null
I need to do this to speed up the script as there are tens of thousands of lines where column b is null and I do not need to import these lines. However, the above code returns no data, either meaning the code must be wrong or it thinks the field b is not null. An example of 2 lines of the text file is:
1,2,3 x,,z
And I only want the line(s) where the second column is occupied.
I hope I've explained that well and again, any help is appreciated.
*ANSWER**
Import-Csv -Delimiter "," -Header @("a","b","c") -Path $testCSV | Select a,b | Where-Object { $_.b -ne '' }
Re: update. Import-Csv treats consecutive delimiters as an empty string, not $null. An empty string, , is not equal to $null any more than 0 is. You want to use Where-Object { b -ne
} or Where-Object { b.Trim() -ne }
Thank you for the answer. I got a “CommandNotFoundException” error with this code as it didn't recognize 'b'. However it did directly lead me to the answer……:: Where-Object { $_.b -ne
}
Lack of column headers is no problem. The cmdlet Import-CSV can specify headers with -Header switch. Assuming test data is saved as C:\temp\headerless.csv and contains
val11,val12,val13,val14 val21,val22,val23,val24 val31,val32,val33,val34
Importing it as CSV is trivial:
Import-Csv -Delimiter "," -Header @("a","b","c","d") -Path C:\temp\headerless.csv
#Output a b c d - - - - val11 val12 val13 val14 val21 val22 val23 val24 val31 val32 val33 val34
Selecting just columns a and b is not hard either:
Import-Csv -Delimiter "," -Header @("a","b","c","d") -Path C:\temp\headerless.csv | select a,b | ft -auto
#Output a b - - val11 val12 val21 val22 val31 val32
You had the right idea. You were splitting the data on commas. However you were not doing this on every line. Just the file as a whole which was the source of your woes.
Get-Content $testCSV | ForEach-Object{ $split = $_ -split "," $FirstColumn = $split[0] }
That would split each line individually and then you could have populated the $FirstColumn variable.
Count processes:
PS /home/manu> Get-Process sudo | Measure-Object -Line Lines Words Characters Property ----- ----- ---------- -------- 1 PS /home/manu> Get-Process *smb | Measure-Object -Line Lines Words Characters Property ----- ----- ---------- -------- 3
PS > Get-VM | Get-Snapshot | Format-Table VM,Name,Created
VMware get snapshot:
PS > Get-VM | Get-Snapshot | Format-Table VM,Name,Created VM Name Created -- ---- ------- VM1 _VCB-BACKUP_ 09/03/2010 20:33:28 VM2 _VCB-BACKUP_ 11/03/2010 20:34:26 VM3 _VCB-BACKUP_ 10/12/2009 20:00:31 VM4 Avant déplacement DB vers D 16/11/2009 14:19:22 VM5 Avant MAJ Powershell v2 04/11/2009
PowerCLI: List snapshots and send by email:
Add-PSSnapin VMware.VimAutomation.Core Connect-VIServer "VC_server_name" -User "Administrateur" -Password "password" $strOutFile = "C:\Scripts\Snapshots\snapshot_list.htm" $head = "<style>" $head = $head + "BODY{background-color:white;}" $head = $head + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}" $head = $head + "TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:thistle}" $head = $head + "TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:PaleGoldenrod}" $head = $head + "</style>" # Info SMTP $smtpServer = "smtp.test.com" $strFrom = " mailfrom@test.com" $strTo = " mailto@test.com" $strSubject = "Snapshot list - " + (get-date -DisplayHint date) $strBody = "Attached is the list of Snapshots" $strMail = "<H2><u>" + $strSubject + "</u></H2>" # Liste des VMs $vms = Get-VM # -------------- Logic ----------------------------- $myCol = @() ForEach ($vm in $vms) { $snapshots = Get-SnapShot -VM $vm if ($snapshots.Name.Length -ige 1 -or $snapshots.length) { ForEach ($snapshot in $snapshots) { $myObj = "" | Select-Object VM, Snapshot, Created, Description $myObj.VM = $vm.name $myObj.Snapshot = $snapshot.name $myObj.Created = $snapshot.created $myObj.Description = $snapshot.description $myCol += $myObj } } } $myCol | Sort-Object VM | ConvertTo-HTML -Head $head -Body $strMail | Out-File $strOutFile $msg = new-object Net.Mail.MailMessage $att = new-object Net.Mail.Attachment($strOutFile) $smtp = new-object Net.Mail.SmtpClient($smtpServer) $msg.From = $strFrom $msg.To.Add($strTo) $msg.Subject = $strSubject $msg.IsBodyHtml = 1 $msg.Body = Get-Content $strOutFile $msg.Attachments.Add($att) $msg.Headers.Add("message-id", "<3BD50098E401463AA228377848493927-1>") $smtp.Send($msg) Disconnect-VIServer