User Tools

Site Tools


windows:win_powershell

Windows PowerSHELL scripting

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

Get start date of a process

PS C:\> Get-Process -name powershell | fl -property name,id,starttime
Name      : powershell
Id        : 3980
StartTime : 29/03/2017 10:52:07

Managing columns

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

References

windows/win_powershell.txt · Last modified: 2021/01/01 21:25 (external edit)