Skip to content

Instantly share code, notes, and snippets.

@abombss
Created August 30, 2012 21:24
Show Gist options
  • Save abombss/3541455 to your computer and use it in GitHub Desktop.
Save abombss/3541455 to your computer and use it in GitHub Desktop.
Handy Powershell Cmdlets
Function Where-ObjectMatches() {
[CmdletBinding(DefaultParameterSetName="MatchLike")]
Param(
[Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
[Alias("Value", "Input", "Object", "io")]
[psobject[]]$InputObject,
[Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true,Position=1)]
[Alias("Selector")]
[psobject]$Property,
[Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="MatchLike",Position=2)]
[string[]] $Like,
[Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="MatchRegex",Position=3)]
[Alias("Match")]
[string[]] $Regex,
[switch]$Not = $false
);
process {
foreach($obj in $InputObject) {
if ($Property -is [string]) { $value = $obj.$Property }
elseif ($Property -is [scriptblock]) { $_ = $obj; $value = &$Property; }
else { throw "Property was $($Property.GetType().ToString()), but must be a string or scriptblock" }
switch ($pscmdlet.ParameterSetName) {
"MatchLike" { [scriptblock] $matchExpression = {$value -like $matcher}; $matchers = $Like }
"MatchRegex" { [scriptblock] $matchExpression = {$value -match $matcher}; $matchers = $Regex }
}
foreach($matcher in $matchers) {
if ($Not -ne (&$matchExpression)) {
$obj
}
}
}
}
<#
.Synopsis
Performs filtering on a set of objects evaluating multiple matching wildcards or regular expressions
.Description
.Parameter InputObject
The objects to filter
.Parameter Property
A property name or scriptblock that returns the value to match against. A scriptblock should use the $_ variable to access to the current object.
.Parameter Like
A list of match expressions to filter on, uses the -like operator to perform matching. It does support wildcards.
.Parameter Regex
A list of regular expression strings to filter on, uses the -match operator to perform the matching
.Parameter Not
Inverts the matching to output everything that doesn't match any of the matchers
.Example
# Outputs the Name property and all Time properties
Get-Item . | %{ $_.psobject.properties } | Where-ObjectMatches Name -Like *Time*, Name
.Example
# Outputs the Name property and all Time properties
Get-Item . | %{ $_.psobject.properties } | Where-ObjectMatches Name -Regex .*Time.*, ^Name
.Example
# Outputs all properties other than Name or Time
Get-Item . | %{ $_.psobject.properties } | Where-ObjectMatches Name -Not -Like *Time*, Name
#>
}
Function Convert-ToHashtable() {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
[psobject[]] $InputObject,
[Parameter(Position=1)]
[ValidateNotNull()]
[string[]] $Include = @("*"),
[ValidateNotNull()]
[string[]] $Exclude = @()
)
process {
foreach($obj in $InputObject) {
$hashtable = @{}
if ($obj -ne $null) {
$props = $obj.psobject.properties | Where-ObjectMatches Name -Like $Include
if ($Exclude.Count -gt 0) {
$props = $props | Where-ObjectMatches Name -Not -Like $Exclude
}
foreach($prop in $props) {
$hashtable[$prop.Name] = $prop.Value
}
}
$hashtable
}
}
<#
.Synopsis
Converts an object to a hashtable
.Description
Converts an object to a hashtable
.Parameter InputObject
The objects to convert
.Parameter Include
A list properties to include, it can contain wildcards. The Default is everything @("*")
.Parameter Exclude
A list properties to include, it can contain wildcards. The Default is none
.Example
# Outputs the The Name and Time properties of an item to a hashtable
Get-Item . | Convert-ToHashtable Name,*Time*
.Example
# Outputs all properties of the item except the Name property to a hashtable
Get-Item . | Convert-ToHashtable -Exclude Name,*Time*
.Inputs
[psobject]
.Outputs
[hashtable]
#>
}
Function Merge-Hashtable() {
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[Alias("src", "s")]
[object]$Source = $null,
[Alias("t")]
[object]$Target = @{},
[Alias("i")]
[string[]]$Include = @(),
[Alias("e", "x", "ex")]
[string[]]$Exclude = @(),
[Alias("f")]
[switch]$Force = $false
);
if ($Source -eq $null) {
} else {
foreach($key in $Source.GetEnumerator() | Select -ExpandProperty Key) {
[bool]$mergeKey = $false;
$value = $Source[$key];
$kvstring = "{Key=$key;Value=$($Source[$key])}"
if ( ($Include -eq $null) -or ($Include.Count -eq 0)) {
$mergeKey = $true;
Write-Debug "Including $kvstring because there is no Include list"
} else {
foreach($filter in $Include) {
if ($key -like $filter) {
$mergeKey = $true;
Write-Debug "Including $kvstring because it matched `"$filter`" in Include list"
continue;
}
}
if (!$mergeKey) {
Write-Debug "Skipping $kvstring because it did not match any filter in the Include list"
}
}
if ($mergeKey) {
foreach($filter in $Exclude) {
if ($key -like $filter) {
$mergeKey = $false
Write-Debug "Excluding $kvstring because it matched `"$filter`" in Exclude list"
continue;
}
}
}
if ( $mergeKey -and ($Target.ContainsKey($key)) -and $Force -ne $true) {
$mergeKey = $false
Write-Debug "Excluding $kvstring because it already exists in Target and the Force parameter was not used"
}
if ($mergeKey) {
if ( $pscmdlet.ShouldProcess($kvstring) ) {
Write-Verbose "Writing $kvstring to target"
$Target[$key] = $value
}
}
} # end foreach $key loop
} # end if source -eq $null
$Target
<#
.SYNOPSIS
Merges a Source and Target hashtables or dictionaries and returns the Target
.DESCRIPTION
Merges a Source and Target hashtable or dictionary and returns the Target
* Easily filter keys on sources to produce desired output using Include and Exclude filter lists with wildcards
* Prevent overwriting keys by default, use -Force to overwrite keys from source on target
* Use $DebugPreference='Continue' to view rich output of what gets include and what doesn't
* Use -WhatIf to see what keys and values would be merged from source
* Use any source or target type that supports the following features (hashtable, dictionary<T>)
* Source requires a GetEnumerator() method that returns some object that has a Key property
* Source must be able to retrieve values of keys using index notation source[$key] returns $value
* Target must have a ContainsKey($key) method that returns $true or $false if the key already exists
* Target must support adding and overwriting values using index notation $target[$key] = $Value
.PARAMETER Source
A hashtable or dictionary or even PSBoundParametersDictionary to copy keys and values from
.PARAMETER Target
A hashtable or dictionary or even PSBoundParametersDictionary to copy keys and values to
.PARAMETER Include
A list of filters to match against source key names for inclusion in the target,
by default all keys will be moved unless an Include filter is used, then only matching
keys will be moved. Include filters are evaluated before any Exclude filters.
.PARAMETER Exclude
A list of filters to match against source key names for exclusion in the target,
by default all keys will be moved unless an Exclude filter is used. Then only those
keys matching the Exclude filter will not be moved. The Exclude filters are evaluated
after any Include filters.
.PARAMETER Force
$true to overwrite keys from the source that already exist in the target
.EXAMPLE
# Merge-Hashtable -Source @{Foo='bar';Chicken='goose'} -Target @{baz='bam'}
Description
-----------
Returns @{baz='bam';Foo='bar';Chicken='goose'}
.EXAMPLE
# Merge-Hashtable -Source @{Foo='bar';Chicken='goose'} -Target @{Foo='Foo';baz='bam'}
Description
-----------
Returns @{baz='bam';Foo='Foo';Chicken='goose'}
the key Foo is not overwritten in the target because the -Force switch was not used.
.EXAMPLE
# Merge-Hashtable -Source @{Foo='bar';Chicken='goose'} -Target @{Foo='Foo';baz='bam'} -Force
Description
-----------
Returns @{baz='bam';Foo='bar';Chicken='goose'}
the key Foo is overwritten in the target because the -Force switch was used.
.EXAMPLE
$source = @{fee=1;fi=2;fo=3;fum=4;foo=5;chicken='balk';duck='quack';goose='honk'}
$target = @{foo=10}
# Merge-Hashtable -Source $source -Target $target -Include fo*,c*
Description
-----------
Returns @{foo=10;fo=3;chicken='balk'}
* Only keys from the source matching $key -like 'fo*' or $key -like 'c*' are merged @(fo, foo, chicken)
* The key Foo is not overwritten in the target because the -Force switch was not used.
.EXAMPLE
$source = @{fee=1;fi=2;fo=3;fum=4;foo=5;chicken='balk';duck='quack';goose='honk'}
$target = @{foo=10}
# Merge-Hashtable -Source $source -Target $target -Include f*,c* -Exclude fo*
Description
-----------
Returns @{foo=10;fee=1;fi=2;fum=4}
* Only keys from the source matching $key -like 'f*' or $key -like 'c*' are merged @(fee, fi, fo, fum, foo, chicken)
* Keys matching $key -like fo* are then excluded @(fo, foo)
.EXAMPLE
$source = @{src_1=1;src_2=2;src_3=3;usr_1=1;usr_2=2;usr_3=3}
# Merge-Hashtable -Source $source -Target @{} -Exclude src_*
Description
-----------
Returns @{usr_1=1;usr_2=2;usr_3=3}
* Filters all the src_* keys from the hashtable
#>
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment