Todo lo que le interesa sobre las matricesEverything you wanted to know about arrays

Las matrices son una característica de lenguaje fundamental de la mayoría de los lenguajes de programación.Arrays are a fundamental language feature of most programming languages. Son una colección de valores u objetos que son difíciles de evitar.They're a collection of values or objects that are difficult to avoid. Vamos a profundizar en las matrices y en todo lo que tienen que ofrecer.Let's take a close look at arrays and everything they have to offer.

Nota

La versión original de este artículo se publicó en el blog escrito por @KevinMarquette.The original version of this article appeared on the blog written by @KevinMarquette. El equipo de PowerShell agradece a Kevin que comparta este contenido con nosotros.The PowerShell team thanks Kevin for sharing this content with us. Visite su blog en PowerShellExplained.com.Please check out his blog at PowerShellExplained.com.

¿Qué es una matriz?What is an array?

Voy a empezar con una descripción técnica básica sobre qué son las matrices y cómo se usan en la mayoría de los lenguajes de programación antes de pasar a las otras formas en que PowerShell las usa.I'm going to start with a basic technical description of what arrays are and how they are used by most programming languages before I shift into the other ways PowerShell makes use of them.

Una matriz es una estructura de datos que actúa como una colección de varios elementos.An array is a data structure that serves as a collection of multiple items. Puede iterar por la matriz o acceder a elementos individuales mediante un índice.You can iterate over the array or access individual items using an index. La matriz se crea como un fragmento secuencial de memoria donde cada valor se almacena justo al lado del otro.The array is created as a sequential chunk of memory where each value is stored right next to the other.

Hablaré sobre cada uno de los detalles a medida que avanzamos.I'll touch on each of those details as we go.

Uso básicoBasic usage

Dado que las matrices son una característica básica de PowerShell, existe una sintaxis sencilla para trabajar con ellas en PowerShell.Because arrays are such a basic feature of PowerShell, there is a simple syntax for working with them in PowerShell.

Creación de una matrizCreate an array

Se puede crear una matriz vacía mediante @().An empty array can be created by using @()

PS> $data = @()
PS> $data.count
0

Podemos crear una matriz e inicializarla con valores, con tan solo colocarlos dentro del paréntesis @().We can create an array and seed it with values just by placing them in the @() parentheses.

PS> $data = @('Zero','One','Two','Three')
PS> $data.count
4

PS> $data
Zero
One
Two
Three

Esta matriz tiene cuatro elementos.This array has 4 items. Cuando llamamos a la variable $data, vemos la lista de nuestros elementos.When we call the $data variable, we see the list of our items. Si es una matriz de cadenas, obtenemos una línea por cadena.If it's an array of strings, then we get one line per string.

Se puede declarar una matriz en varias líneas.We can declare an array on multiple lines. En este caso, la coma es opcional y, en general, se excluye.The comma is optional in this case and generally left out.

$data = @(
    'Zero'
    'One'
    'Two'
    'Three'
)

Prefiero declarar mis matrices en varias líneas de esa forma.I prefer to declare my arrays on multiple lines like that. No solo es más fácil de leer cuando tiene varios elementos, sino que también facilita la comparación con versiones anteriores cuando se usa el control de código fuente.Not only does it get easier to read when you have multiple items, it also makes it easier to compare to previous versions when using source control.

Otra sintaxisOther syntax

Normalmente, se entiende que @() es la sintaxis para crear una matriz, pero las listas separadas por comas funcionan en la mayoría de las ocasiones.It's commonly understood that @() is the syntax for creating an array, but comma-separated lists work most of the time.

$data = 'Zero','One','Two','Three'

Write-Output para crear matricesWrite-Output to create arrays

Un pequeño truco que merece la pena mencionar es que puede usar Write-Output para crear cadenas en la consola rápidamente.One cool little trick worth mentioning is that you can use Write-Output to quickly create strings at the console.

$data = Write-Output Zero One Two Three

Esto resulta útil porque no es necesario colocar comillas alrededor de las cadenas cuando el parámetro acepta cadenas.This is handy because you don't have to put quotes around the strings when the parameter accepts strings. Nunca haría esto en un script, pero se puede hacer en la consola.I would never do this in a script but it's fair game in the console.

Acceso a elementosAccessing items

Ahora que tiene una matriz con elementos, puede acceder a ellos y actualizarlos.Now that you have an array with items in it, you may want to access and update those items.

OffsetOffset

Para acceder a elementos individuales, usamos los corchetes [] con un valor de desplazamiento que comienza en 0.To access individual items, we use the brackets [] with an offset value starting at 0. Así es como obtenemos el primer elemento de la matriz:This is how we get the first item in our array:

PS> $data = 'Zero','One','Two','Three'
PS> $data[0]
Zero

El motivo por el que usamos cero aquí es porque el primer elemento está al principio de la lista, por lo que usamos un desplazamiento de 0 elementos para acceder a él.The reason why we use zero here is because the first item is at the beginning of the list so we use an offset of 0 items to get to it. Para llegar al segundo elemento, es necesario usar un desplazamiento de 1 para omitir el primer elemento.To get to the second item, we would need to use an offset of 1 to skip the first item.

PS> $data[1]
One

Esto significa que el último elemento está en el desplazamiento 3.This would mean that the last item is at offset 3.

PS> $data[3]
Three

ÍndiceIndex

Ahora puede ver por qué seleccioné esos valores para este ejemplo.Now you can see why I picked the values that I did for this example. He presentado esto como un desplazamiento porque eso es lo que realmente es, pero a este desplazamiento se le conoce de forma más común como un índice.I introduced this as an offset because that is what it really is, but this offset is more commonly referred to as an index. Un índice que comienza en 0.An index that starts at 0. En el resto de este artículo, utilizaremos el término índice para hacer referencia al desplazamiento.For the rest of this article I will call the offset an index.

Trucos especiales sobre índicesSpecial index tricks

En la mayoría de los lenguajes, solo puede especificar un único número como el índice, y se obtendrá un solo elemento.In most languages, you can only specify a single number as the index and you get a single item back. PowerShell es mucho más flexible.PowerShell is much more flexible. Puede usar varios índices a la vez.You can use multiple indexes at once. Al proporcionar una lista de índices, podemos seleccionar varios elementos.By providing a list of indexes, we can select several items.

PS> $data[0,2,3]
Zero
Two
Three

Los elementos se devuelven según el orden de los índices proporcionados.The items are returned based on the order of the indexes provided. Si duplica un índice, obtendrá ese elemento las dos veces.If you duplicate an index, you get that item both times.

PS> $data[3,0,3]
Three
Zero
Three

Podemos especificar una secuencia de números con el operador .. integrado.We can specify a sequence of numbers with the built-in .. operator.

PS> $data[1..3]
One
Two
Three

Esto también funciona en orden inverso.This works in reverse too.

PS> $data[3..1]
Three
Two
One

Puede usar valores de índice negativos para desplazarse desde el final.You can use negative index values to offset from the end. Por lo tanto, si necesita el último elemento de la lista, puede usar -1.So if you need the last item in the list, you can use -1.

PS> $data[-1]
Three

Hay que tener cuidado aquí con el operador ...One word of caution here with the .. operator. Las secuencias 0..-1 y -1..0 dan como resultado los valores 0,-1 y -1,0.The sequence 0..-1 and -1..0 evaluate to the values 0,-1 and -1,0. Es fácil ver $data[0..-1] y pensar que enumeraría todos los elementos si olvida este detalle.It's easy to see $data[0..-1] and think it would enumerate all items if you forget this detail. $data[0..-1] proporciona el mismo valor que $data[0,-1] al proporcionar el primer y último elemento de la matriz, y ninguno de los demás valores.$data[0..-1] gives you the same value as $data[0,-1] by giving you the first and last item in the array (and none of the other values).

Fuera de los límitesOut of bounds

En la mayoría de los lenguajes, si intenta acceder a un índice de un elemento que va más allá del final de la matriz, obtendría algún tipo de error o una excepción.In most languages, if you try to access an index of an item that is past the end of the array, you would get some type of error or an exception. PowerShell no devuelve nada de forma silenciosa.PowerShell silently returns nothing.

PS> $null -eq $data[9000]
True

No se puede indexar en una matriz NULLCannot index into a null array

Si la variable es $null e intenta indexarla como una matriz, obtendrá una excepción System.Management.Automation.RuntimeException con el mensaje Cannot index into a null array.If your variable is $null and you try to index it like an array, you get a System.Management.Automation.RuntimeException exception with the message Cannot index into a null array.

PS> $empty = $null
SP> $empty[0]
Error: Cannot index into a null array.

Por lo tanto, asegúrese de que las matrices no son $null antes de intentar acceder a los elementos que contienen.So make sure your arrays are not $null before you try to access elements inside them.

CountCount

Las matrices y otras colecciones tienen una propiedad Count que indica cuántos elementos hay en la matriz.Arrays and other collections have a count property that tells you how many items are in the array.

PS> $data.count
4

PowerShell 3.0 agregó una propiedad Count a la mayoría de los objetos.PowerShell 3.0 added a count property to most objects. Puede tener un solo objeto y debe proporcionar un recuento de 1.you can have a single object and it should give you a count of 1.

PS> $date = Get-Date
PS> $date.count
1

Incluso $null tiene una propiedad Count, salvo que devuelve 0.Even $null has a count property except it returns 0.

PS> $null.count
0

Hay algunas excepciones aquí que revisaré cuando trate la búsqueda de $null o matrices vacías más adelante en este artículo.There are some traps here that I will revisit when I cover checking for $null or empty arrays later on in this article.

Errores puntualesOff-by-one errors

Se crea un error de programación común porque las matrices empiezan en el índice 0.A common programming error is created because arrays start at index 0. Los errores puntuales pueden introducirse de dos maneras.Off-by-one errors can be introduced in two ways.

Lo primero sería pensar que desea el segundo elemento y usa un índice de 2 y obtiene realmente el tercer elemento.The first is by mentally thinking you want the second item and using an index of 2 and really getting the third item. O bien, piense que tiene cuatro elementos y desea el último elemento, por lo que usa el recuento para acceder al último elemento.Or by thinking that you have four items and you want last item, so you use the count to access the last item.

$data[ $data.count ]

PowerShell puede permitirle hacer eso y proporcionar exactamente el elemento que existe en el índice 4: $null.PowerShell is perfectly happy to let you do that and give you exactly what item exists at index 4: $null. Debe usar $data.count - 1 o -1, dos parámetros sobre los que hemos obtenido información anteriormente.You should be using $data.count - 1 or the -1 that we learned about above.

PS> $data[ $data.count - 1 ]
Three

Aquí es donde puede usar el índice -1 para obtener el último elemento.This is where you can use the -1 index to get the last element.

PS> $data[ -1 ]
Three

Lee Dailey también me dijo que podemos usar $data.GetUpperBound(0) para obtener el número de índice máximo.Lee Dailey also pointed out to me that we can use $data.GetUpperBound(0) to get the max index number.

PS> $data.GetUpperBound(0)
3
PS> $data[ $data.GetUpperBound(0) ]
Three

La segunda forma más común es al iterar la lista y no detenerse en el momento adecuado.The second most common way is when iterating the list and not stopping at the right time. Lo revisaré cuando hablemos sobre el uso del bucle for.I'll revisit this when we talk about using the for loop.

Actualización de elementosUpdating items

Podemos usar el mismo índice para actualizar los elementos existentes en la matriz.We can use the same index to update existing items in the array. Esto nos proporciona acceso directo para actualizar elementos individuales.This gives us direct access to update individual items.

$data[2] = 'dos'
$data[3] = 'tres'

Si se intenta actualizar un elemento que está más allá del último elemento, se obtiene un error Index was outside the bounds of the array..If we try to update an item that is past the last element, then we get an Index was outside the bounds of the array. error.

PS> $data[4] = 'four'
Index was outside the bounds of the array.
At line:1 char:1
+ $data[4] = 'four'
+ ~~~~~~~~~~~~~
+ CategoryInfo          : OperationStopped: (:) [], IndexOutOfRangeException
+ FullyQualifiedErrorId : System.IndexOutOfRangeException

Revisaré esto más adelante cuando hable sobre cómo aumentar una matriz.I'll revisit this later when I talk about how to make an array larger.

IteraciónIteration

En el algún momento, puede que necesite recorrer la lista completa o iterar por ella para realizar alguna acción en cada elemento de la matriz.At some point, you might need to walk or iterate the entire list and perform some action for each item in the array.

CanalizaciónPipeline

Las matrices y la canalización de PowerShell están diseñadas para complementarse.Arrays and the PowerShell pipeline are meant for each other. Esta es una de las formas más sencillas de procesar dichos valores.This is one of the simplest ways to process over those values. Al pasar una matriz a una canalización, cada elemento contenido en la matriz se procesa individualmente.When you pass an array to a pipeline, each item inside the array is processed individually.

PS> $data = 'Zero','One','Two','Three'
PS> $data | ForEach-Object {"Item: [$PSItem]"}
Item: [Zero]
Item: [One]
Item: [Two]
Item: [Three]

Si no ha visto $PSItem antes, solo tiene que saber que es lo mismo que $_.If you have not seen $PSItem before, just know that it's the same thing as $_. Puede usar cualquiera de ellos, ya que ambos representan el objeto actual de la canalización.You can use either one because they both represent the current object in the pipeline.

Bucle forEachForEach loop

El bucle ForEach funciona bien con las colecciones.The ForEach loop works well with collections. Uso de la sintaxis: foreach ( <variable> in <collection> )Using the syntax: foreach ( <variable> in <collection> )

foreach ( $node in $data )
{
    "Item: [$node]"
}

Método forEachForEach method

Tiendo a olvidarme de él, pero funciona bien con operaciones sencillas.I tend to forget about this one but it works well for simple operations. PowerShell le permite llamar a .ForEach() en una colección.PowerShell allows you to call .ForEach() on a collection.

PS> $data.foreach({"Item [$PSItem]"})
Item [Zero]
Item [One]
Item [Two]
Item [Three]

.foreach() adopta un parámetro que es un bloque de script.The .foreach() takes a parameter that is a script block. Puede quitar los paréntesis y simplemente proporcionar el bloque de script.You can drop the parentheses and just provide the script block.

$data.foreach{"Item [$PSItem]"}

Se trata de una sintaxis menos conocida, pero funciona exactamente igual.This is a lesser known syntax but it works just the same. Este método foreach se agregó en PowerShell 4.0.This foreach method was added in PowerShell 4.0.

Bucle ForFor loop

El bucle for se usa mucho en muchos de los otros lenguajes, pero no se ve con frecuencia en PowerShell.The for loop is used heavily in most other languages but you don't see it much in PowerShell. Cuando lo vea, suele ser en el contexto de recorrer una matriz.When you do see it, it's often in the context of walking an array.

for ( $index = 0; $index -lt $data.count; $index++)
{
    "Item: [{0}]" -f $data[$index]
}

Lo primero que hacemos es inicializar $index en 0.The first thing we do is initialize an $index to 0. A continuación, agregamos la condición de que $index debe ser inferior a $data.count.Then we add the condition that $index must be less than $data.count. Por último, se especifica que cada vez que se crea un bucle, el índice se debe aumentar en 1.Finally, we specify that every time we loop that me must increase the index by 1. En este caso, $index++ es la forma abreviada de $index = $index + 1.In this case $index++ is short for $index = $index + 1.

Siempre que use un bucle for, preste especial atención a la condición.Whenever you're using a for loop, pay special attention to the condition. He usado $index -lt $data.count aquí.I used $index -lt $data.count here. Es fácil obtener una condición algo incorrecta para obtener un error puntual en la lógica.It's easy to get the condition slightly wrong to get an off-by-one error in your logic. El uso de $index -le $data.count o $index -lt ($data.count - 1) siempre suele generar algún error.Using $index -le $data.count or $index -lt ($data.count - 1) are ever so slightly wrong. Esto haría que el resultado procesara demasiados o muy pocos elementos.That would cause your result to process too many or too few items. Este es el típico error puntual.This is the classic off-by-one error.

Bucle switchSwitch loop

Es fácil pasarlo por alto.This is one that is easy to overlook. Si proporciona una matriz a una instrucción switch, esta comprueba cada elemento de la matriz.If you provide an array to a switch statement, it checks each item in the array.

$data = 'Zero','One','Two','Three'
switch( $data )
{
    'One'
    {
        'Tock'
    }
    'Three'
    {
        'Tock'
    }
    Default
    {
        'Tick'
    }
}
Tick
Tock
Tick
Tock

Hay muchas cosas interesantes que podemos hacer con la instrucción switch.There are a lot of cool things that we can do with the switch statement. Tengo otro artículo dedicado a esto.I have another article dedicated to this.

Actualización de valoresUpdating values

Cuando la matriz es una colección de cadenas o enteros (tipos de valor), puede que a veces desee actualizar los valores de la matriz a medida que se recorren en bucle.When your array is a collection of string or integers (value types), sometimes you may want to update the values in the array as you loop over them. La mayoría de los bucles anteriores usan una variable en el bucle que contiene una copia del valor.Most of the loops above use a variable in the loop that holds a copy of the value. Si actualiza esa variable, no se actualiza el valor original de la matriz.If you update that variable, the original value in the array is not updated.

La excepción a esa instrucción es el bucle for.The exception to that statement is the for loop. Si desea recorrer una matriz y actualizar los valores que contiene, el bucle for es lo que busca.If you want to walk an array and update values inside it, then the for loop is what you're looking for.

for ( $index = 0; $index -lt $data.count; $index++ )
{
    $data[$index] = "Item: [{0}]" -f $data[$index]
}

En este ejemplo, se adopta un valor para el índice, se realizan algunos cambios y, después, se usa ese mismo índice para volver a asignarlo.This example takes a value by index, makes a few changes, and then uses that same index to assign it back.

Matrices de objetosArrays of Objects

Hasta ahora, lo único que hemos colocado en una matriz es un tipo de valor, pero las matrices también pueden contener objetos.So far, the only thing we've placed in an array is a value type, but arrays can also contain objects.

$data = @(
    [pscustomobject]@{FirstName='Kevin';LastName='Marquette'}
    [pscustomobject]@{FirstName='John'; LastName='Doe'}
)

Muchos cmdlets devuelven colecciones de objetos como matrices cuando se asignan a una variable.Many cmdlets return collections of objects as arrays when you assign them to a variable.

$processList = Get-Process

Todas las características básicas de las que ya se ha hablado también se aplican a las matrices de objetos con algunos detalles que merece la pena destacar.All of the basic features we already talked about still apply to arrays of objects with a few details worth pointing out.

Acceso a las propiedadesAccessing properties

Se puede usar un índice para acceder a un elemento individual de una colección, de la misma forma que con los tipos de valor.We can use an index to access an individual item in a collection just like with value types.

PS> $data[0]

FirstName LastName
-----     ----
Kevin     Marquette

Se puede acceder a las propiedades y actualizarlas directamente.We can access and update properties directly.

PS> $data[0].FirstName

Kevin

PS> $data[0].FirstName = 'Jay'
PS> $data[0]

FirstName LastName
-----     ----
Jay       Marquette

Propiedades de las matricesArray properties

Normalmente, tendría que enumerar la lista completa de la siguiente forma para acceder a todas las propiedades:Normally you would have to enumerate the whole list like this to access all the properties:

PS> $data | ForEach-Object {$_.LastName}

Marquette
Doe

También puede usar el cmdlet Select-Object -ExpandProperty.Or by using the Select-Object -ExpandProperty cmdlet.

PS> $data | Select-Object -ExpandProperty LastName

Marquette
Doe

Pero PowerShell nos ofrece la posibilidad de solicitar LastName directamente.But PowerShell offers us the ability to request LastName directly. PowerShell realiza la enumeración automáticamente y devuelve una lista limpia.PowerShell enumerates them all for us and returns a clean list.

PS> $data.LastName

Marquette
Doe

Aún así, se realiza la enumeración, pero no vemos la complejidad subyacente.The enumeration still happens but we don't see the complexity behind it.

Filtrado con Where-ObjectWhere-Object filtering

Aquí es donde Where-Object entra en acción, de tal forma que se permite filtrar y seleccionar lo que se desee fuera de la matriz en función de las propiedades del objeto.This is where Where-Object comes in so we can filter and select what we want out of the array based on the properties of the object.

PS> $data | Where-Object {$_.FirstName -eq 'Kevin'}

FirstName LastName
-----     ----
Kevin     Marquette

Se puede escribir esa misma consulta para obtener el elemento FirstName que se busca.We can write that same query to get the FirstName we are looking for.

$data | Where FirstName -eq Kevin

Where()Where()

Las matrices tienen un método Where() que permite especificar un elemento scriptblock para el filtro.Arrays have a Where() method on them that allows you to specify a scriptblock for the filter.

$data.Where({$_.FirstName -eq 'Kevin'})

Esta característica se agregó en PowerShell 4.0.This feature was added in PowerShell 4.0.

Actualización de objetos en buclesUpdating objects in loops

Con los tipos de valor, la única manera de actualizar la matriz es usar un bucle for, porque es necesario conocer el índice para reemplazar el valor.With value types, the only way to update the array is to use a for loop because we need to know the index to replace the value. Hay más opciones con objetos porque son tipos de referencia.We have more options with objects because they are reference types. Este es un ejemplo rápido:Here is a quick example:

foreach($person in $data)
{
    $person.FirstName = 'Kevin'
}

Este bucle recorre todos los objetos de la matriz $data.This loop is walking every object in the $data array. Dado que los objetos son tipos de referencia, la variable $person hace referencia al mismo objeto que se encuentra en la matriz.Because objects are reference types, the $person variable references the exact same object that is in the array. Por tanto, las actualizaciones de sus propiedades actualizan el original.So updates to its properties do update the original.

Todavía no se puede reemplazar todo el objeto de esta manera.You still can't replace the whole object this way. Si se intenta asignar un nuevo objeto a la variable $person, se actualiza la referencia de variable a otro elemento que ya no apunta al objeto original de la matriz.If you try to assign a new object to the $person variable, you're updating the variable reference to something else that no longer points to the original object in the array. Esto no funciona como cabría esperar:This doesn't work like you would expect:

foreach($person in $data)
{
    $person = [pscustomobject]@{
        FirstName='Kevin'
        LastName='Marquette'
    }
}

OperadoresOperators

Los operadores de PowerShell también sirven para las matrices.The operators in PowerShell also work on arrays. Algunos de ellos funcionan de manera ligeramente diferente.Some of them work slightly differently.

-join-join

El operador -join es el más obvio, por lo que vamos a profundizar en él primero.The -join operator is the most obvious one so let's look at it first. Me gusta el operador -join y lo uso con frecuencia.I like the -join operator and use it often. Combina todos los elementos de la matriz con el carácter o la cadena que se especifique.It joins all elements in the array with the character or string that you specify.

PS> $data = @(1,2,3,4)
PS> $data -join '-'
1-2-3-4
PS> $data -join ','
1,2,3,4

Una de las características que me gustan del operador -join es que controla elementos individuales.One of the features that I like about the -join operator is that it handles single items.

PS> 1 -join '-'
1

Lo utilizo dentro de registros y mensajes detallados.I use this inside logging and verbose messages.

PS> $data = @(1,2,3,4)
PS> "Data is $($data -join ',')."
Data is 1,2,3,4.

-join $array-join $array

Este es un truco inteligente que Lee Dailey me indicó.Here is a clever trick that Lee Dailey pointed out to me. Si alguna vez se desea combinar todo sin un delimitador, en lugar de hacer esto:If you ever want to join everything without a delimiter, instead of doing this:

PS> $data = @(1,2,3,4)
PS> $data -join $null
1234

Se puede usar -join con la matriz como parámetro sin prefijo.You can use -join with the array as the parameter with no prefix. Eche un vistazo a este ejemplo para saber de qué estoy hablando.Take a look at this example to see that I'm talking about.

PS> $data = @(1,2,3,4)
PS> -join $data
1234

-replace y -split-replace and -split

Los otros operadores, como -replace y -split, se ejecutan en cada elemento de la matriz.The other operators like -replace and -split execute on each item in the array. No puedo decir que siempre lo he utilizado de esta forma, pero aquí se muestra un ejemplo.I can't say that I have ever used them this way but here is an example.

PS> $data = @('ATX-SQL-01','ATX-SQL-02','ATX-SQL-03')
PS> $data -replace 'ATX','LAX'
LAX-SQL-01
LAX-SQL-02
LAX-SQL-03

-contains-contains

El operador -contains permite comprobar una matriz de valores para ver si contiene un valor especificado.The -contains operator allows you to check an array of values to see if it contains a specified value.

PS> $data = @('red','green','blue')
PS> $data -contains 'green'
True

-in-in

Si tiene un valor único que le gustaría comprobar si coincide con alguno de varios valores, puede usar el operador -in.When you have a single value that you would like to verify matches one of several values, you can use the -in operator. El valor se encontraría a la izquierda y la matriz en el lado derecho del operador.The value would be on the left and the array on the right-hand side of the operator.

PS> $data = @('red','green','blue')
PS> 'green' -in $data
True

Esto puede resultar complicado si la lista es grande.This can get expensive if the list is large. A menudo, utilizo un patrón regex si voy a comprobar más de unos pocos valores.I often use a regex pattern if I'm checking more than a few values.

PS> $data = @('red','green','blue')
PS> $pattern = "^({0})$" -f ($data -join '|')
PS> $pattern
^(red|green|blue)$

PS> 'green' -match $pattern
True

-eq y -ne-eq and -ne

La igualdad con las matrices puede resultar complicada.Equality and arrays can get complicated. Cuando la matriz está en el lado izquierdo, se compara cada elemento.When the array is on the left side, every item gets compared. En lugar de devolver True, se devuelve el objeto con el que existe una coincidencia.Instead of returning True, it returns the object that matches.

PS> $data = @('red','green','blue')
PS> $data -eq 'green'
green

Cuando se usa el operador -ne, se obtienen todos los valores que no son iguales a nuestro valor.When you use the -ne operator, we get all the values that are not equal to our value.

PS> $data = @('red','green','blue')
PS> $data -ne 'green'
red
blue

Cuando se usa esto en una instrucción if(), el valor devuelto es True.When you use this in an if() statement, a value that is returned is a True value. Si no se devuelve ningún valor, se trata de un valor False.If no value is returned, then it's a False value. En ambos casos, las instrucciones siguientes se evalúan como True.Both of these next statements evaluate to True.

$data = @('red','green','blue')
if ( $data -eq 'green' )
{
    'Green was found'
}
if ( $data -ne 'green' )
{
    'And green was not found'
}

Examinaré esto cuando hablemos de las pruebas de $null.I'll revisit this in a moment when we talk about testing for $null.

-match-match

El operador -match intenta coincidir con cada elemento de la colección.The -match operator tries to match each item in the collection.

PS> $servers = @(
    'LAX-SQL-01'
    'LAX-API-01'
    'ATX-SQL-01'
    'ATX-API-01'
)
PS> $servers -match 'SQL'
LAX-SQL-01
ATX-SQL-01

Cuando se usa -match con un solo valor, una variable especial $Matches se rellena con información de coincidencia.When you use -match with a single value, a special variable $Matches gets populated with match info. Esto no sucede cuando una matriz se procesa de esta manera.This isn't the case when an array is processed this way.

Se puede adoptar el mismo enfoque con Select-String.We can take the same approach with Select-String.

$servers | Select-String SQL

Vamos a profundizar más sobre Select-String, -match y la variable $matches en otra publicación titulada Las distintas formas de usar regex.I take a closer look at Select-String,-match and the $matches variable in another post called The many ways to use regex.

$null o valores vacíos$null or empty

La prueba de $null o de matrices vacías puede resultar complicada.Testing for $null or empty arrays can be tricky. Estas son las excepciones comunes con las matrices.Here are the common traps with arrays.

A primera vista, parece que esta instrucción debería funcionar.At a glance, this statement looks like it should work.

if ( $array -eq $null)
{
    'Array is $null'
}

Sin embargo, acabo de observar cómo -eq comprueba cada elemento de la matriz.But I just went over how -eq checks each item in the array. Por tanto, puede haber una matriz de varios elementos con un solo valor $null, que se evaluaría como $trueSo we can have an array of several items with a single $null value and it would evaluate to $true

$array = @('one',$null,'three')
if ( $array -eq $null)
{
    'I think Array is $null, but I would be wrong'
}

Esta es la razón por la que se recomienda colocar $null a la izquierda del operador.This is why it's a best practice to place the $null on the left side of the operator. Esto hace que este escenario no plantee problemas.This makes this scenario a non-issue.

if ( $null -eq $array )
{
    'Array actually is $null'
}

Una matriz $null no es lo mismo que una matriz vacía.A $null array isn't the same thing as an empty array. Si se sabe que existe una matriz, compruebe el número de objetos que contiene.If you know you have an array, check the count of objects in it. Si la matriz es $null, el recuento es 0.If the array is $null, the count is 0.

if ( $array.count -gt 0 )
{
    "Array isn't empty"
}

Hay otra excepción que hay que tener en cuenta aquí.There is one more trap to watch out for here. Se puede usar count incluso si tiene un solo objeto, a menos que ese objeto sea PSCustomObject.You can use the count even if you have a single object, unless that object is a PSCustomObject. Se trata de un error que se corrigió en PowerShell 6.1.This is a bug that is fixed in PowerShell 6.1. Es algo positivo, pero hay muchas personas que aún usan la versión 5.1 y, por tanto, es necesario tenerlo en cuenta.That's good news, but a lot of people are still on 5.1 and need to watch out for it.

PS> $object = [PSCustomObject]@{Name='TestObject'}
PS> $object.count
$null

Si todavía usa PowerShell 5.1, puede encapsular el objeto en una matriz antes de comprobar el recuento para obtener un número preciso.If you're still on PowerShell 5.1, you can wrap the object in an array before checking the count to get an accurate count.

if ( @($array).count -gt 0 )
{
    "Array isn't empty"
}

Para hacerlo con seguridad, compruebe $null y, después, el recuento.To fully play it safe, check for $null, then check the count.

if ( $null -ne $array -and @($array).count -gt 0 )
{
    "Array isn't empty"
}

All -eqAll -eq

Recientemente observé que alguien preguntó cómo comprobar que todos los valores de una matriz coinciden con un valor determinado.I recently saw someone ask how to verify that every value in an array matches a given value. El usuario de Reddit /u/bis tenía esta solución inteligente que comprueba si hay valores incorrectos y, después, cambia el resultado.Reddit user /u/bis had this clever solution that checks for any incorrect values and then flips the result.

$results = Test-Something
if ( -not ( $results -ne 'Passed') )
{
    'All results a Passed'
}

Adición a matricesAdding to arrays

Llegados a este punto, se empieza a preguntar cómo agregar elementos a una matriz.At this point, you're starting to wonder how to add items to an array. La respuesta rápida es que no se puede.The quick answer is that you can't. Una matriz tiene un tamaño de memoria fijo.An array is a fixed size in memory. Si necesita aumentarlo o agregar un solo elemento a ella, se debe crear una matriz y copiar todos los valores de la matriz anterior.If you need to grow it or add a single item to it, then you need to create a new array and copy all the values over from the old array. Esto suena trabajoso, pero PowerShell elimina la complejidad de crear la matriz.This sounds like a lot of work, however, PowerShell hides the complexity of creating the new array. PowerShell implementa el operador de suma (+) para las matrices.PowerShell implements the addition operator (+) for arrays.

Nota

PowerShell no implementa una operación de resta.PowerShell does not implement a subtraction operation. Si quiere una alternativa flexible a una matriz, debe usar un objeto List genérico.If you want a flexible alternative to an array, you need to use a generic List object.

Adición de matricesArray addition

Se puede usar el operador de suma con matrices para crear una matriz.We can use the addition operator with arrays to create a new array. Por lo tanto, dadas estas dos matrices:So given these two arrays:

$first = @(
    'Zero'
    'One'
)
$second = @(
    'Two'
    'Three'
)

Se pueden agregar juntas para obtener una nueva matriz.We can add them together to get a new array.

PS> $first + $second

Zero
One
Two
Three

Signos más e igual (+=)Plus equals +=

Se puede crear una matriz en contexto y agregarle un elemento similar al siguiente:We can create a new array in place and add an item to it like this:

$data = @(
    'Zero'
    'One'
    'Two'
    'Three'
)
$data += 'four'

Recuerde que cada vez que se use +=, se duplica y crea una matriz.Just remember that every time you use += that you're duplicating and creating a new array. Esto no es un problema para los conjuntos de datos pequeños, pero el escalado es muy deficiente.This is a not an issue for small datasets but it scales extremely poorly.

Asignación de canalizaciónPipeline assignment

Se pueden asignar los resultados de cualquier canalización en una variable.You can assign the results of any pipeline into a variable. Se trata de una matriz si contiene varios elementos.It's an array if it contains multiple items.

$array = 1..5 | ForEach-Object {
    "ATX-SQL-$PSItem"
}

Normalmente, al pensar en el uso de la canalización, viene a la mente la típica integración de PowerShell.Normally when we think of using the pipeline, we think of the typical PowerShell one-liners. Se puede utilizar la canalización con instrucciones foreach() y otros bucles.We can leverage the pipeline with foreach() statements and other loops. Por lo tanto, en lugar de agregar elementos a una matriz en un bucle, se pueden colocar elementos en la canalización.So instead of adding items to an array in a loop, we can drop items onto the pipeline.

$array = foreach ( $node in (1..5))
{
    "ATX-SQL-$node"
}

Tipos de matrizArray Types

De forma predeterminada, una matriz de PowerShell se crea como un tipo [PSObject[]].By default, an array in PowerShell is created as a [PSObject[]] type. Esto permite que contenga cualquier tipo de objeto o valor.This allows it to contain any type of object or value. Esto funciona porque todo se hereda del tipo PSObject.This works because everything is inherited from the PSObject type.

Matrices fuertemente tipadasStrongly typed arrays

Se puede crear una matriz de cualquier tipo con una sintaxis similar.You can create an array of any type using a similar syntax. Cuando se crea una matriz fuertemente tipada, solo puede contener valores u objetos del tipo especificado.When you create a strongly typed array, it can only contain values or objects the specified type.

PS> [int[]] $numbers = 1,2,3
PS> [int[]] $numbers2 = 'one','two','three'
ERROR: Cannot convert value "one" to type "System.Int32". Input string was not in a correct format."

PS> [string[]] $strings = 'one','two','three'

ArrayListArrayList

Agregar elementos a una matriz es una de sus mayores limitaciones, pero hay algunas otras colecciones que se pueden usar para solucionar este problema.Adding items to an array is one of its biggest limitations, but there are a few other collections that we can turn to that solve this problem.

ArrayList suele ser una de las primeras soluciones a las que se recurre cuando se necesita una matriz con la que se pueda trabajar más rápido.The ArrayList is commonly one of the first things that we think of when we need an array that is faster to work with. Actúa como una matriz de objetos cada vez que se necesita, pero puede agregar los elementos con rapidez.It acts like an object array every place that we need it, but it handles adding items quickly.

Aquí se muestra cómo se crea un elemento ArrayList y cómo se le agregan elementos.Here is how we create an ArrayList and add items to it.

$myarray = [System.Collections.ArrayList]::new()
[void]$myArray.Add('Value')

Se recurre a .NET para obtener este tipo.We are calling into .NET to get this type. En este caso, se usa el constructor predeterminado para crearlo.In this case, we are using the default constructor to create it. A continuación, se llama al método Add para agregarle un elemento.Then we call the Add method to add an item to it.

La razón por la que uso [void] al principio de la línea es para suprimir el código de retorno.The reason I'm using [void] at the beginning of the line is to suppress the return code. Algunas llamadas a .NET permiten hacer esto y pueden crear resultados inesperados.Some .NET calls do this and can create unexpected output.

Si los únicos datos que hay en la matriz son cadenas, eche un vistazo al uso de StringBuilder.If the only data that you have in your array is strings, then also take a look at using StringBuilder. Es prácticamente lo mismo, pero tiene algunos métodos que solo se utilizan para tratar cadenas.It's almost the same thing but has some methods that are just for dealing with strings. StringBuilder está diseñado especialmente para el rendimiento.The StringBuilder is specially designed for performance.

Es habitual que las personas pasen a ArrayList desde las matrices.It's common to see people move to ArrayList from arrays. Pero esto pertenece a una época en la que C# no contaba con compatibilidad genérica.But it comes from a time where C# didn't have generic support. La compatibilidad de ArrayList con el elemento List[] genérico ha quedado en desuso.The ArrayList is deprecated in support for the generic List[]

Lista genéricaGeneric List

Un tipo genérico es un tipo especial de C# que define una clase generalizada, y el usuario especifica los tipos de datos que usa cuando se crea.A generic type is a special type in C# that defines a generalized class and the user specifies the data types it uses when created. Por lo tanto, si se desea una lista de números o cadenas, hay que especificar que se desea una lista de tipos int o string.So if you want a list of numbers or strings, you would define that you want list of int or string types.

Aquí se muestra cómo crear una lista de cadenas.Here is how you create a List for strings.

$mylist = [System.Collections.Generic.List[string]]::new()

También podría ser una lista de números.Or a list for numbers.

$mylist = [System.Collections.Generic.List[int]]::new()

Se puede convertir una matriz existente en una lista como esta sin crear primero el objeto:We can cast an existing array to a list like this without creating the object first:

$mylist = [System.Collections.Generic.List[int]]@(1,2,3)

Se puede acortar la sintaxis con la instrucción using namespace en PowerShell 5 y versiones posteriores.We can shorten the syntax with the using namespace statement in PowerShell 5 and newer. La instrucción using debe ser la primera línea del script.The using statement needs to be the first line of your script. Al declarar un espacio de nombres, PowerShell permite dejarlo fuera de los tipos de datos cuando se hace referencia a ellos.By declaring a namespace, PowerShell lets you leave it off of the data types when you reference them.

using namespace System.Collections.Generic
$myList = [List[int]]@(1,2,3)

Esto hace que List sea mucho más fácil de usar.This makes the List much more usable.

Tiene un método Add similar a su disposición.You have a similar Add method available to you. A diferencia de ArrayList, no hay ningún valor devuelto en el método Add, por lo que no tenemos que aplicarle el elemento void.Unlike the ArrayList, there is no return value on the Add method so we don't have to void it.

$myList.Add(10)

De esta forma, aún se puede acceder a los elementos como otras matrices.And we can still access the elements like other arrays.

PS> $myList[-1]
10

List[PSObject]List[PSObject]

Puede haber una lista de cualquier tipo, pero cuando no se conozca el tipo de objetos, se puede usar [List[PSObject]] para contenerlos.You can have a list of any type, but when you don't know the type of objects, you can use [List[PSObject]] to contain them.

$list = [List[PSObject]]::new()

Remove()Remove()

ArrayList y el elemento List[] genérico admiten la eliminación de elementos de la colección.The ArrayList and the generic List[] both support removing items from the collection.

using namespace System.Collections.Generic
$myList = [List[string]]@('Zero','One','Two','Three')
[void]$myList.Remove("Two")
Zero
One
Three

Cuando se trabaja con tipos de valor, se quita el primero de la lista.When working with value types, it removes the first one from the list. Puede llamarlo una y otra vez para seguir quitando ese valor.You can call it over and over again to keep removing that value. Si se tienen tipos de referencia, se debe proporcionar el objeto que se desea quitar.If you have reference types, you have to provide the object that you want removed.

[list[System.Management.Automation.PSDriveInfo]]$drives = Get-PSDrive
$drives.remove($drives[2])
$delete = $drives[2]
$drives.remove($delete)

El método Remove devuelve true si pudo encontrar y quitar el elemento de la colección.The remove method returns true if it was able to find and remove the item from the collection.

Más coleccionesMore collections

Hay muchas otras colecciones que se pueden usar, pero estas son las sustituciones de matrices genéricas adecuadas.There are many other collections that can be used but these are the good generic array replacements. Si le interesa obtener más información sobre estas opciones, eche un vistazo a este gist que Mark Kraus ha organizado.If you're interested in learning about more of these options, take a look at this Gist that Mark Kraus put together.

Otros maticesOther nuances

Ahora que he tratado toda la funcionalidad principal, aquí hay algunas cuestiones más que quería mencionar antes de terminar.Now that I have covered all the major functionality, here are a few more things that I wanted to mention before I wrap this up.

Matrices con un tamaño establecido previamentePre-sized arrays

He mencionado que no se puede cambiar el tamaño de una matriz una vez creada.I mentioned that you can't change the size of an array once it's created. Se puede crear una matriz de un tamaño determinado previamente si se le llama con el constructor new($size).We can create an array of a pre-determined size by calling it with the new($size) constructor.

$data = [Object[]]::new(4)
$data.count
4

Multiplicación de matricesMultiplying arrays

Un truquito interesante es que se puede multiplicar una matriz por un entero.An interesting little trick is that you can multiply an array by an integer.

PS> $data = @('red','green','blue')
PS> $data * 3
red
green
blue
red
green
blue
red
green
blue

Inicialización con 0Initialize with 0

Un escenario común es la intención de crear una matriz que contenga solo ceros.A common scenario is that you want to create an array with all zeros. Si solo va a haber enteros, una matriz fuertemente tipada de enteros, de forma predeterminada, solo contendrá ceros.If you're only going to have integers, a strongly typed array of integers defaults to all zeros.

PS> [int[]]::new(4)
0
0
0
0

Se puede utilizar el truco de la multiplicación para hacer esto.We can use the multiplying trick to do this too.

PS> $data = @(0) * 4
PS> $data
0
0
0
0

Lo bueno del truco de la multiplicación es que se puede usar cualquier valor.The nice thing about the multiplying trick is that you can use any value. Por lo tanto, si se prefiere tener 255 como valor predeterminado, sería una buena forma de hacerlo.So if you would rather have 255 as your default value, this would be a good way to do it.

PS> $data = @(255) * 4
PS> $data
255
255
255
255

Matrices anidadasNested arrays

Una matriz dentro de una matriz se denomina matriz anidada.An array inside an array is called a nested array. No la utilizo mucho en PowerShell, pero sí la he usado más en otros lenguajes.I don't use these much in PowerShell but I have used them more in other languages. Considere la posibilidad de usar una matriz de matrices cuando los datos se ajusten a un patrón tipo cuadrícula.Consider using an array of arrays when your data fits in a grid like pattern.

A continuación, se muestran dos formas de crear una matriz bidimensional.Here are two ways we can create a two-dimensional array.

$data = @(@(1,2,3),@(4,5,6),@(7,8,9))

$data2 = @(
    @(1,2,3),
    @(4,5,6),
    @(7,8,9)
)

La coma es muy importante en esos ejemplos.The comma is very important in those examples. Proporcioné un ejemplo anterior de una matriz normal en varias líneas donde la coma era opcional.I gave an earlier example of a normal array on multiple lines where the comma was optional. Esto no sucede con una matriz multidimensional.That isn't the case with a multi-dimensional array.

La forma en que se usa la notación de índice cambia ligeramente ahora que hay una matriz anidada.The way we use the index notation changes slightly now that we've a nested array. Con el elemento $data anterior, esta es la forma en que se accedería al valor 3.Using the $data above, this is how we would access the value 3.

PS> $outside = 0
PS> $inside = 2
PS> $data[$outside][$inside]
3

Agregue un par de corchetes para cada nivel de anidamiento de matriz.Add a set of bracket for each level of array nesting. El primer par de corchetes es para la matriz más externa y, después, empiece a trabajar a partir de ahí.The first set of brackets is for the outer most array and then you work your way in from there.

Write-Output -NoEnumerateWrite-Output -NoEnumerate

En PowerShell, se suelen desajustar o enumerar las matrices.PowerShell likes to unwrap or enumerate arrays. Este es un aspecto fundamental de la forma en que PowerShell usa la canalización, pero hay ocasiones en las que no se desea que esto sea así.This is a core aspect of the way PowerShell uses the pipeline but there are times that you don't want that to happen.

Normalmente, los objetos se canalizan hacia Get-Member para obtener más información sobre ellos.I commonly pipe objects to Get-Member to learn more about them. Al canalizar una matriz hacia ahí, se desajusta, y Get-Member ve los miembros de la matriz y no la matriz real.When I pipe an array to it, it gets unwrapped and Get-Member sees the members of the array and not the actual array.

PS> $data = @('red','green','blue')
PS> $data | Get-Member
TypeName: System.String
...

Para evitar que se desajuste la matriz, se puede usar Write-Object -NoEnumerate.To prevent that unwrap of the array, you can use Write-Object -NoEnumerate.

PS> Write-Output -NoEnumerate $data | Get-Member
TypeName: System.Object[]
...

Existe una segunda forma que es más que un truco, y trato de evitar trucos como este.I have a second way that's more of a hack (and I try to avoid hacks like this). Se puede colocar una coma delante de la matriz antes de canalizarla.You can place a comma in front of the array before you pipe it.

PS> ,$data | Get-Member
TypeName: System.Object[]
...

Devolución de una matrizReturn an array

Este desajuste de matrices también se produce cuando se generan o se devuelven valores a partir de una función.This unwrapping of arrays also happens when you output or return values from a function. También se puede obtener una matriz si se asigna la salida a una variable, por lo que esto no suele ser un problema.You can still get an array if you assign the output to a variable so this isn't commonly an issue.

El problema es que hay una nueva matriz.The catch is that you have a new array. Si surge algún problema, puede usar Write-Output -NoEnumerate $array o return ,$array para solucionarlo.If that is ever a problem, you can use Write-Output -NoEnumerate $array or return ,$array to work around it.

¿Algo más?Anything else?

Sé que esto es mucho para asimilar.I know this is all a lot to take in. Espero que aprenda algo de este artículo cada vez que lo lea y que se convierta en una buena referencia a la que recurrir a largo plazo.My hope is that you learn something from this article every time you read it and that it turns out to be a good reference for you for a long time to come. Si le ha resultado útil, compártalo con otras personas a las que crea que puede servir.If you found this to be helpful, please share it with others you think may get value out of it.

Ahora, recomendaría consultar una publicación similar que escribí sobre las tablas hash.From here, I would recommend you check out a similar post that I wrote about hashtables.