Búsqueda de sitios web

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-Object

Luego 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
    }
} #foreach

Por 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 function

La 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.

Artículos relacionados