Data.ps1
|
# Copyright (c) Microsoft Corporation. # Licensed under the MIT License. function ConvertTo-PsObject { <# .SYNOPSIS Convert a set of variables into a PsObject .DESCRIPTION Constructs new PsObject from the available variables. Simplifies packing of data into one object that Powershell can work with. Alias: construct .PARAMETER Args All parameters are detected dynamically. You should pass here names of the variables you'd like to convert into the PsObject. .EXAMPLE $a = "a_value" $b = [int] 5 $c = "one", "two" construct a b c Constructs PsObject with properties a, b and c. Values are taken from variables $a, $b and $c. #> $properties = [ordered] @{} foreach( $name in $args ) { $local = Get-Variable $name -Scope local -ea Ignore if( $local ) { $properties.$name = $local.Value; continue } $script = Get-Variable $name -Scope script -ea Ignore if( $script ) { $properties.$name = $script.Value; continue } $global = Get-Variable $name -Scope global -ea Ignore if( $global ) { $properties.$name = $global.Value; continue } Write-Warning "Could not resolve variable with name '$name'" } New-Object -TypeName PSObject -Property $properties } function ConvertTo-Hash( [object] $object ) { <# .SYNOPSIS Convert an object into a hash table .DESCRIPTION This function takes any object, gets all not $false properties and creates hash table out of the found properties. This can be useful to pass some object through a process boundary or to remove property from an object. .PARAMETER Object Object to deconstruct into hash table .EXAMPLE ConvertTo-Hash (ls | select -f 1) Get hash table from the first found child item. #> $hash = [ordered] @{} $object | foreach{ $psitem.PsObject.Members } | where MemberType -match "^(Note)?Property$" | foreach Name | where{ $object.$psitem } | foreach{ $hash[$psitem] = $object.$psitem } $hash } function Get-Parameter { <# .SYNOPSIS Get names of all available parameters from input objects .DESCRIPTION This filter analyses what parameters are present in all objects passed to the filter and outputs all unique parameter names. .PARAMETER Pattern Constrain output only to parameter names that match this pattern. By default all parameter names are returned. .PARAMETER Single Specify this switch if there must be only one parameter that match the pattern. If there is no single matching parameter, exception is thrown. .EXAMPLE Get-ChildItem | Get-Parameter List all available parameters from Get-ChildItem command. Both file info and directory info parameter names will be listed. .EXAMPLE Get-Process | Get-Parameter priority List all parameters for Process object (returned from Get-Process) that contain 'priority' substring in the parameter name. 'priority' here is a regex. .LINK Use-Project Use-Filter #> param ( [string] $Pattern = ".*", [switch] $Single ) begin { $accumulator = @() } process { $accumulator += $psitem } end { if( -not $accumulator ) { return } # Get properties that match the pattern $result = @( $accumulator | foreach{ $psitem.PsObject.Members } | where Name -match $pattern | where MemberType -match "Property" | foreach Name | Get-UniqueUnsorted) # Need to return all entries if( -not $single ) { return $result } # No ambulation with matches if( $result.Length -eq 1 ) { return $result[0] } # Strict match disambiguation if( @($result | where{ $psitem -eq $pattern }).Length -eq 1 ) { return $pattern } # Warn user about ambulation Write-Warning "Disambiguate '$pattern'`n$($result | Out-String)" } } function Use-Project { <# .SYNOPSIS Project several parameters from input objects .DESCRIPTION This command performs project operation from relational algebra with not strict column name matching. It allows to compress data output only to the columns you are interested in. You are not forced to specify full column names to do so. You only need to supply enough info to perform unambiguous column name match. It makes working with table-like date more interactive and less time consuming. Behavior is very similar to Select-Object with not strict (but unambiguous) properties specified. Alias: p .PARAMETER Args Pass as many column name patterns as you like - they would be parsed dynamically. .EXAMPLE Get-ChildItem | Use-Project name len Would output Name and Length properties of all child items. Projection doesn't require you to specify full property name if you can supply unambiguous matching regex pattern. .EXAMPLE Get-ChildItem | Use-Project name time WARNING: Disambiguate 'time' CreationTime CreationTimeUtc LastAccessTime LastAccessTimeUtc LastWriteTime LastWriteTimeUtc Would output warning showing that 'time' parameter is ambiguous and there are 6 parameter names that match it. You must supply more specific parameter name so the match would be unambiguous. [The same command via aliases] ls | p name time .LINK Get-Parameter Use-Filter #> begin { $accumulator = @() } process { $accumulator += $psitem } end { # Display available parameters if no arguments are specified if( $args.Count -eq 0 ) { Write-Warning "What property?`n$($accumulator | Get-Parameter | Out-String)"; return } # Resolve all passed parameter names $resolved = [string[]] @($args | foreach{ $accumulator | Get-Parameter $psitem -Single } ) # Output all resolved parameters # If there is an unresolved parameter do nothing if( $args.Count -eq $resolved.Count ) { $accumulator | Select-Object -Property $resolved } } } function Use-Filter { <# .SYNOPSIS Regex based parameter filter for input objects .DESCRIPTION Filters pipeline passing through only objects that match specific property and value pattern. Allows to quickly explore data and discover property names and values. Alias: f .PARAMETER ParameterPattern Regex pattern for a parameter. Only not ambiguous matches are accepted. All ambiguities are explained via Warnings. If parameter pattern is omitted, all existing property names are shown. .PARAMETER ValuePattern Regex pattern for a parameter value. Only not ambiguous matches are accepted. All ambiguities are explained via Warnings. If value pattern is omitted, all existing property values are shown. .PARAMETER NoValue Specify this switch if you want to filter properties that match property pattern but have no value. .EXAMPLE PS> Get-ChildItem | Use-Filter name PS> ls | f name ps1 Exploring Get-ChildItem output. Output unique values for a property that match 'name' pattern. Then specify ps1 files for the name. .EXAMPLE ls | f len -NoValue Filter ls output, find files which don't have Length property set. .LINK Get-Parameter Use-Project #> param ( [string] $ParameterPattern, [string] $ValuePattern, [switch] $NoValue ) begin { $accumulator = @() } process { $accumulator += $psitem } end { # Display available parameters if no parameter pattern is specified if( -not $parameterPattern ) { Write-Warning "What property?`n$($accumulator | Get-Parameter | Out-String)"; return } # Resolve parameter name $parameter = $accumulator | Get-Parameter $parameterPattern -Single if( -not $parameter ) { return } # No value special case if( $noValue ) { return $accumulator | where{ -not $psitem.$parameter } } # Display all values if no value pattern is specified if( -not $valuePattern ) { Write-Warning "What value?`n$($accumulator | foreach{ $psitem.$parameter } | Get-UniqueUnsorted | Out-String)"; return } # Output object that has matches in property and value $accumulator | where{ $psitem.$parameter -match $valuePattern } } } function Get-Ini { <# .SYNOPSIS Parse INI file as a hashtable object .DESCRIPTION Features: - Both section and section-less parameters are supported. - Comments are supported. - Non-literal names are supported. - Collapsing of empty sections is supported. .PARAMETER Path Path to INI file. Can't be used at the same time with Content. .PARAMETER KeepEmptySections Specify this switch if you want to keep empty INI sections in the output. By default empty sections are removed. .PARAMETER Content Content of the INI file. Can't be used at the same time with Path. .PARAMETER Comment Regex that specifies how comments are started in ini file. By default: ; .EXAMPLE Get-Ini Shared.ini Parse Shared.ini file. .LINK Show-Ini http://stackoverflow.com/questions/417798/ini-file-parsing-in-powershell #> param ( [string] $Path, [switch] $KeepEmptySections, [string[]] $Content, [string] $Comment = ";" ) # Parameter validation if( $path -and $content ) { throw "It is not possible to specify both -Path and -Content parameters" } # Initialize $section = "" $ini = [ordered]@{} $ini[$section] = [ordered]@{} $content = if( $content ) { $content -split "`r?`n" } else { Get-Content $path } # Parsing foreach( $line in $content ) { $withoutComments = ($line -replace "$comment.*").Trim() if( $withoutComments.Length -eq 0 ) { continue } switch -regex ($withoutComments) { "^\[([^\]]+)\]\s*$" { $section = $matches[1].Trim() $ini[$section] = [ordered]@{} } "^([^=]+)\s*=\s*(.*)?\s*$" { $name, $value = $matches[1..2] $ini[$section][$name.Trim()] = $value } default { Write-Warning "Unknown sentence '$line' in file '$path'. Skipping the line." } } } # Remove empty sections by creating a new object since in # ConstrainedMode we can't use methods like $ini.Remove() if( -not $KeepEmptySections ) { $newIni = [ordered]@{} $ini.keys | where{ $ini[$psitem].Count -gt 0 } | foreach{ $newIni[$psitem] = $ini.$psitem } $ini = $newIni } # Copy entries from no-section if it's possible if( $ini[""] -and $ini[""].Keys ) { $withoutSection = @($ini[""].Keys) | where{ @($ini.keys) -notcontains $psitem } $withoutSection | foreach{ $ini[$psitem] = $ini[""][$psitem] } } $ini } function ConvertFrom-Ini { <# .SYNOPSIS Converts ini strings into Powershell hashtable object .DESCRIPTION Features: - Both section and section-less parameters are supported. - Comments are supported. - Non-literal names are supported. - Collapsing of empty sections is supported. .PARAMETER Content Content of an INI file. .PARAMETER Comment Regex that specifies how comments are started in ini file. By default: ; .PARAMETER KeepEmptySections Specify this switch if you want to keep empty INI sections in the output. By default empty sections are removed. .EXAMPLE ConvertFrom-Ini (Get-Content Shared.ini) Convert content of Shared.ini file to a hashtable object. .LINK http://stackoverflow.com/questions/417798/ini-file-parsing-in-powershell #> param ( [string[]] $Content, [string] $Comment = ";", [switch] $KeepEmptySections ) # Initialize $section = "" $ini = [ordered]@{} $ini[$section] = [ordered]@{} $content = $content -split "`r?`n" # Parsing foreach( $line in $content ) { $withoutComments = ($line -replace "$comment.*").Trim() if( $withoutComments.Length -eq 0 ) { continue } switch -regex ($withoutComments) { "^\[([^\]]+)\]\s*$" { $section = $matches[1].Trim() $ini[$section] = [ordered]@{} } "^([^=]+)\s*=\s*(.*)?\s*$" { $name, $value = $matches[1..2] $ini[$section][$name.Trim()] = $value } default { Write-Warning "Unknown sentence '$line' in file '$path'. Skipping the line." } } } # Remove empty sections by creating a new object since in # ConstrainedMode we can't use methods like $ini.Remove() if( -not $KeepEmptySections ) { $newIni = [ordered]@{} $ini.keys | where{ $ini[$psitem].Count -gt 0 } | foreach{ $newIni[$psitem] = $ini.$psitem } $ini = $newIni } # Copy entries from no-section if it's possible if( $ini[""] -and $ini[""].Keys ) { $withoutSection = @($ini[""].Keys) | where{ @($ini.keys) -notcontains $psitem } $withoutSection | foreach{ $ini[$psitem] = $ini[""][$psitem] } } $ini } function Import-Ini { <# .SYNOPSIS Imports ini file into Powershell hashtable object .DESCRIPTION Features: - Both section and section-less parameters are supported. - Comments are supported. - Non-literal names are supported. - Collapsing of empty sections is supported. .PARAMETER Path Path to an existing INI file. .PARAMETER Comment Regex that specifies how comments are started in ini file. By default: ; .PARAMETER KeepEmptySections Specify this switch if you want to keep empty INI sections in the output. By default empty sections are removed. .EXAMPLE Import-Ini Shared.ini Convert content of Shared.ini file to a hashtable object. .LINK http://stackoverflow.com/questions/417798/ini-file-parsing-in-powershell #> param ( [Parameter(Mandatory = $true)] [ValidateScript({Test-Path $psitem -PathType Leaf})] [string] $Path, [string] $Comment = ";", [switch] $KeepEmptySections ) $content = Get-Content $path ConvertFrom-Ini $content -Comment:$Comment -KeepEmptySections:$KeepEmptySections } function Show-Ini { <# .SYNOPSIS Print contents of INI parsed file, received from Get-Ini command .DESCRIPTION Formats INI file in hash table form to make it console-readable. You can specify section filter to get only the sections of interest at the moment. .PARAMETER Ini Content of a INI file in hash table form. Usually it is out from Get-Ini command. .PARAMETER SectionFilter Filter that should pass each section in order to be outputted. By default all sections are shown. .EXAMPLE Show-Ini (Get-Ini Shared.ini) machine Print all sections of Shared.ini containing 'machine' word. .LINK Get-Ini #> param ( [hashtable] $Ini, [string] $SectionFilter = ".*" ) foreach( $section in ($ini.Keys | sort | where{ $psitem -match $sectionFilter }) ) { $section foreach( $key in $ini[$section].keys ) { " $($key) = $($ini[$section][$key])" } "" } } |