Comparación de nombres de propiedades de PowerShell
Recientemente, estuve charlando con mi amiga Gladys Kravitz sobre la molestia de comparar objetos en PowerShell. Incluso después de todos estos años. Tiene un caso de uso específico, pero es posible que también sienta la necesidad de una mejor opción de comparación. Y para ser claros, la comparación de la que estamos hablando no son los valores del objeto, como puedes ver con Comparar-Objeto. Sino más bien los nombres de propiedades.
En la situación de Gladys, importa datos de archivos CSV que procesa a través de sus scripts para hacer las cosas. Su caso de uso es comparar nombres de propiedades. ¿Este archivo CSV tiene los mismos nombres de propiedad que ese archivo CSV? ¿Hay propiedades adicionales? ¿O falta algo? Así que veamos cómo podemos abordar esto.
Pensar objetos
Aunque comenzamos con archivos CSV, en realidad estamos hablando de objetos. Gladys puede importar sus archivos CSV y convertirlos en objetos personalizados. Es posible que esté creando objetos para comparar mediante algún otro mecanismo. La conclusión es que deberíamos considerar esto como un problema de comparación de objetos, no como un problema de archivos.
Permítanme comenzar generando algunos datos de muestra.
$csvA = @"
samantha,darren-1,darren-2,tabitha,esmerelda
1,2,3,4,5
2,4,6,8,10
3,6,9,11,12
11,22,33,44,55
"@
$csvB = @"
samantha,darren-1,darren-2,esmerelda,gladys,agatha
1,2,3,4,0,9
2,4,6,8,1,8
3,6,9,11,8,0
11,22,33,55,66,77
"@
$a = $csvA | ConvertFrom-Csv
$b = $csvB | ConvertFrom-Csv
Para mis propósitos, $A es el objeto de referencia y $B es el objeto de diferencia. Al observar los datos, puede ver que a $B le falta “tabitha” y tiene propiedades adicionales “agatha” y “gladys”. No me importan los valores. Ni siquiera nos importa el orden de los nombres de las propiedades porque tenemos un objeto al que vamos a hacer referencia por el nombre de la propiedad, no por su posición en el encabezado CSV.
PSObjeto
Para comparar nombres de propiedades de objetos, no necesitamos el objeto completo. Todo lo que necesitamos es un elemento para analizar porque los nombres de las propiedades son los mismos para los objetos. PowerShell se esfuerza mucho para que sea fácil de usar para los profesionales de TI. PowerShell oculta gran parte de la elaboración de salchichas .NET para que usted sólo tenga que trabajar con los resultados finales. Pero a veces necesitamos ensuciarnos las manos. En este caso, usaremos una propiedad ubicua llamada PSObject.
Usaremos la propiedad Propiedades. Esto es lo que parece.
Entonces es fácil crear una lista de nombres de propiedades para los objetos de referencia y diferencia.
$refProp = $a[0].psobject.properties.name | Sort-Object
$diffProp = $b[0].psobject.properties.name | Sort-ObjectLuego puedo revisar cada lista y ver qué propiedades faltan o sobran.
#find extra properties in the difference object
foreach ($name in $diffProp) {
if ($refProp -notcontains $name) {
$name
}
} #foreach
#find missing reference properties from the difference object
foreach ($name in $refProp) {
if ($diffProp -notcontains $name) {
$name
}
} #foreachPor supuesto, quiero crear un resultado significativo para que Gladys pueda saber de un vistazo cómo se comparan las cosas.
Comparar-nombre de propiedad
Aquí está la función de PowerShell que escribí.
Function Compare-PropertyName {
[cmdletbinding(DefaultParameterSetName="default")]
[alias("cpn")]
[Outputtype("PSPropertyNameDifference","string","boolean")]
Param(
[Parameter(Position = 0, Mandatory)]
[ValidateNotNullOrEmpty()]
[object]$Reference,
[Parameter(Position = 1, Mandatory)]
[ValidateNotNullOrEmpty()]
[object]$Difference,
[Parameter(HelpMessage = "Indicate if property names match with a simple True/False.",ParameterSetName="quiet")]
[switch]$Quiet,
[Parameter(HelpMessage = "Only show missing property names in the difference object.",ParameterSetName="missing")]
[switch]$MissingOnly,
[Parameter(HelpMessage = "Only show extra property names in the difference object.",ParameterSetName="extra")]
[switch]$ExtraOnly
)
#get property names from the first item
$refProp = $Reference[0].psobject.properties.name | Sort-Object
Write-Verbose "Found $(($refProp).count) reference properties"
$diffProp = $Difference[0].psobject.properties.name | Sort-Object
Write-Verbose "Found $(($diffProp). count) difference properties"
$missing = [System.Collections.Generic.List[string]]::new()
$extra = [System.Collections.Generic.List[string]]::new()
#find extra properties in the difference object
foreach ($name in $diffProp) {
if ($refProp -notcontains $name) {
Write-Verbose "$Name not found in the reference object"
$extra.Add( $name)
}
} #foreach
#find missing reference properties from the difference object
foreach ($name in $refProp) {
if ($diffProp -notcontains $name) {
Write-Verbose "$Name not found in the difference object"
$missing.Add( $name)
}
} #foreach
#create a custom object for the reseult
$result = [pscustomobject]@{
PSTypename = "PSPropertyNameDifference"
Missing = $missing
Extra = $Extra
ReferenceProperties = $refProp
DifferenceProperties = $diffProp
ReferenceCount = $refProp.count
DifferenceCount = $diffProp.count
}
switch ($pscmdlet.ParameterSetName) {
"Quiet" {
if ($result.missing.count -eq 0 -AND $result.extra.count -eq 0) {
$true
}
else {
$false
}
}
"Missing" {
$result.Missing
}
"Extra" {
$result.Extra
}
Default {
$result
}
} #switch
} #close functionLa función genera un tipo de objeto por defecto.
Pero también quería ofrecer alternativas que le dieran a Gladys la información que pudiera necesitar rápidamente.
Todos los resultados son relativos al objeto de diferencia. Al objeto de diferencia, $b, le falta la propiedad “tabitha”, por ejemplo.
Me encantaría saber cómo funciona esto para usted. Creo que será una buena adición al módulo PSScriptTools, así que espere una actualización en las próximas semanas.




