PowerShell Scripting#

Habilitar ejecución de scripts#

Set-ExecutionPolicy Unrestricted

Tipos y colecciones#

En PowerShell, no es necesario declarar explícitamente el tipo de una variable, infiere el tipo automáticamente al asignar un valor. No obtantes si necesitas definir explícitamente el tipo de una variable, puedes hacerlo usando la notación [tipo].

PS C:\> $number = 42
PS C:\> echo $number.GetType()

IsPublic IsSerial Name
-------- -------- ----
True     True     Int32

PS C:\> [int]$a = 4
PS C:\> $a.GetType().Name
Int32

Podemos convertir los diferentes tipos por ejemplo:

PS C:\> $a=4
PS C:\> $cadena=$a.ToString()
PS C:\> $cadena.GetType().Name
String

#TryParse nos devuelve si es posible
PS C:\> [int]$b
PS C:\> [int]::TryParse($cadena, [ref]$b)
True
PS C:\> echo $b
4
PS C:\> [int]::TryParse("2w", [ref]$b)
False
PS C:\> echo $b
0

#Podemos hacerlo directamente, pero si hay algún error se parará el script
PS C:\> $b = [int]::Parse($cadena)
PS C:\> echo $b
4

Los tipos de variables más comunes que puedes encontrar y utilizar en PowerShell son:

  • Números enteros (Integers). Un entero es un número sin parte decimal

    PS C:\> [int]$a = 4
    PS C:\> $a.GetType().Name
    Int32
    
  • Números de coma flotante (Floating-Point). Los números de coma flotante son números que incluyen una parte decimal

    PS C:\> $number = 3.14
    PS C:\> echo $number.GetType().Name
    Double
    
  • Cadenas de texto (Strings). Una cadena es una secuencia de caracteres utilizada para representar texto.

    PS C:\>$cadena = "Hola, Mundo!"
    PS C:\> echo $cadena.GetType().Name
    String
    
    PS C:\> $a="cadena"
    PS C:\> echo $a
    cadena
    PS C:\> echo $a.Replace("ca","CC")
    CCdena
    PS C:\> echo $a.split("a")
    c
    den
    
    PS C:\> echo $a.Split("a")[0]
    c
    PS C:\> echo $a
    cadena
    PS C:\> echo $a.Substring(2,4)
    dena
    PS C:\> echo $a.Remove(2,4)
    ca
    PS C:\> echo $a.Contains("a")
    True
    PS C:\> echo $a.IndexOf("a")
    1
    PS C:\> echo $a.Replace("ca","Ca")
    Cadena
    PS C:\> echo $a.Equals("cadena")
    True
    PS C:\> echo $a.Length
    6
    PS C:\> echo $a.Contains("an")
    False
    PS C:\> echo $a.ToLower()
    cadena
    PS C:\> echo $a.ToUpper()
    CADENA
    PS C:\> $a.Replace("ca","  ").Replace("na","  ")
     de
    #Trim() elimina espacios al final y al princio
    PS C:\> $a.Replace("ca","  ").Replace("na","  ").Trim()
    de
    

    Format: Formatea una cadena usando marcadores de posición {n} que se reemplazan por los valores proporcionados.

    PS C:\> $nombre = "Tutankamón"
    PS C:\> $edad = 3394
    PS C:\> $cadena = [string]::Format("Nombre: {0}, Edad: {1}", $nombre, $edad)
    

    Redondeo a Dos Decimales

    PS C:\> $pi = 3.141592
    PS C:\> $out = "pi : {0:F2}" -f $pi
    PS C:\> Write-Output $out
    pi : 3,14
    

    Formato de Moneda

    PS C:\> $pi = 3.141592
    PS C:\> $out = "pi : {0:C2}" -f $pi
    PS C:\> Write-Output $out
    pi : 3,14 
    

    Formato Científico

    PS C:\> $pi = 3.141592
    PS C:\> $out = "pi : {0:E2}" -f $pi
    PS C:\> Write-Output $out
    pi : 3,14E+000
    

    Formato de Porcentaje

    PS C:\> $pi = 3.141592
    PS C:\> $out = "pi : {0:P2}" -f $pi
    PS C:\> Write-Output $out
    pi : 314,16 %
    

    Formato de Longitud Fija (Relleno a la Izquierda)

    PS C:\> $pi = 3.141592
    PS C:\> $out = "pi : {0,10}" -f $pi
    PS C:\> Write-Output $out
    pi :   3,141592
    

    Formato de Longitud Fija (Relleno a la Derecha)

    PS C:\> $pi = 3.141592
    PS C:\> $out = "pi : {0,-10}" -f $pi
    PS C:\> Write-Output $out
    pi : 3,141592
    

    Formato con Cero Padding (Relleno con ceros)

    PS C:\> $pi = 3.141592
    PS C:\> $out = "pi : {0:000.000}" -f $pi
    PS C:\> Write-Output $out
    pi : 003,142
    
    PS C:\> $out = "pi : {0:00}" -f $pi
    PS C:\> Write-Output $out
    pi : 03
    
  • Booleanos (Booleans). Un valor booleano puede ser True o False.

    PS C:\>$B=$true
    PS C:\> echo $B.GetType().Name
    Boolean
    
  • Arreglos (Arrays). Un arreglo es una colección de elementos, que pueden ser de cualquier tipo de dato. Los elementos están indexados comenzando desde cero.

    PS C:> $A = @(0)*4
    PS C:> echo $A
    0
    0
    0
    0
    
    PS C:\> $numbers = @(1, 2, 3, 4, 5)
    PS C:\> echo $numbers.GetType().Name
    Object[]
    
    PS C:\> echo $numbers[0]
    1
    
    PS C:\> echo $numbers[0].GetType().Name
    Int32
    
    PS C:> echo $numbers.Length
    5
    PS C:\>  echo $numbers.Count
    5
    
    echo $numbers.Contains(2)
    True
    
    #podemos añadir nuevos elementos
    PS C:\>  $numbers+="hola"
    PS C:\>  echo $numbers
    1
    2
    3
    4
    5
    hola
    PS C:\> echo $numbers.Length
    6
    

    Arrays multidimimensionales

    PS C:> $XY = @(@(1, 2), @(3, 4))
    PS C:>  echo $XY.Length
    2
    
    PS C:>  echo $XY[0] 1
    2
    
    PS C:>  echo $XY[0].Length
    2
    
    PS C:>  echo $XY[0][0]
    1
    
  • Hash Tables (Tablas hash). Una tabla hash es una colección de pares clave-valor. Las claves deben ser únicas dentro de la tabla.

    PS C:\> $person = @{
     Name = "Tutankamón"
     Age = 3358
     City = "Egipto"
    }
    
    PS C:\> echo $person.Name
    Tutankamón
    
    #Agregar una nueva clave
    PS C:\> $person.Estado = "momificado"
    PS C:\>  $person
    
    Name                           Value
    ----                           -----
    Estado                         momificado
    Name                           Tutankamón
    Age                            3358
    City                           Egipto
    
    #eliminar la clave
    PS C:\> $person.Remove("Age")
    PS C:\> $person
    
    Name                           Value
    ----                           -----
    Estado                         momificado
    Name                           Tutankamón
    City                           Egipto
    
  • ScriptBlocks. Un ScriptBlock es un bloque de código que se puede ejecutar más tarde o pasar como un parámetro.

    PS C:\>  $script = { param($name) "Hola, $name!" }
    PS C:\> & $script "Tutankamón"
    Hola, Tutankamón!
    

Operadores#

PS C:\> $a=11
PS C:\> $b=5
PS C:\> $c=$a-$b     # resta
PS C:\> echo $c
6
PS C:\> $c=$a+$b     # suma
PS C:\> echo $c
16
PS C:\> $c=$a*$b     # multiplicación
PS C:\> echo $c
55
PS C:\> $c=$a/$b     # división
PS C:\> echo $c
2,2
PS C:\> $c=$a%$b     # resto o modulo
PS C:\> echo $c
1

Operadores de asignación#

PS C:\> $a=6
PS C:\> $a+=2 ; echo $a   # $a=$a+2
8
PS C:\> $a-=2 ; echo $a   # $a=$a-2
6
PS C:\> $a++  ; echo $a   # $a=$a+1
7
PS C:\> $a--  ; echo $a   # $a=$a-1
6
PS C:\> $a/=2 ; echo $a   # $a=$a/2
3
PS C:\> $a*=3 ; echo $a   # $a=$a*3
9
PS C:\> $a%=3 ; echo $a   # $a=$a%3
0
  • Números aleatorios

    Get-Random # numero aletorio
    Get-Random -Minimum 1 -Maximum 10
    
  • Otras conversiones

    #pasar a binario
    [Convert]::ToString($decimal, 2)
    
    $a="$pwd"
    
    #Podemos ejecutar un texto como si fuese un comando &
    $a="notepad"
    &$a
    

Argumentos de entrada#

Argumentos de entrada Read-Host#

PS C:\> cat read_host.ps1
echo "Dame un entero"
$Name=Read-Host
echo "Sin pasar a int ($Name*$Name) = "
echo $($Name*$Name)
echo ""
$a = [int] $Name
echo "Pasando a int ($Name*$Name) = "
echo $($a*$a)
echo ""

PS C:\> .\read_host.ps1
Dame un entero
2
Sin pasar a int (2*2) =
22

Pasando a int (2*2) =
4

Argumentos de entrada Read-Host argst.ps1#

PS C:\> cat .\argst.ps1
echo "tenemos $args parámetros de entrada"
echo "El argumento 0: $($args[0])"
echo "El argumento 1: $($args[1])"

PS C:\> .\argst.ps1 1 2 3
tenemos 1 2 3 parámetros de entrada
El argumento 0: 1
El argumento 1: 2
PS C:\> cat .\args.ps1
for($i=0;$i -lt $args.Length;$i++)
{
  $salida = $args[$i]
  Write-Output "i = $salida"
}

PS C:\> .\args.ps1 1 dos tres
      i = 1
      i = dos
      i = tres
PS C:\> cat .\argst.ps1
foreach ($i in $args)
{
echo $i
}

PS C:\> .\argst.ps1 1 dos tres 1 dos tres
1
dos
tres
1
dos
tres

Argumentos de entrada Read-Host param.ps1#

PS C:\> cat .\param.ps1
param (
    [string]$Nombre,
    [int]$Nacimiento
)

# Calcular la edad
$Edad = (Get-Date).Year - $Nacimiento

Write-Output "Hola $Nombre, Tienes $Edad"

PS C:\> .\param.ps1 -Nombre Tutankamón -Nacimiento -1334
Hola Tutankamón, Tienes 3358

PS C:\> .\param.ps1 -Nombre Tutankamón
Hola Tutankamón, Tienes 2024

PS C:\> .\param.ps1
Hola , Tienes 2024

En el caso de que queramos darle un valor por defecto cambiamos:

param (
    [string]$Nombre = "Tutankamón",
    [int]$Nacimiento = "-1334"
)

y cuando lo ejecutamos obtenemos:

PS C:\> .\param_def.ps1 -Name Nefertiti -Nacimiento -1370
Hola Tutankamón, Tienes 3394

PS C:\Users\Administrador\powershell> .\param_def.ps1 -Name Nefertiti
Hola Tutankamón, Tienes 3358

PS C:\> .\param_def.ps1
Hola Tutankamón, Tienes 3358

Podemos completar la declaracion de un parámetro en un script de PowerShell utilizando [Parameter()], el argumento Mandatory=$true dentro de la directiva parameter indica que el parámetro es obligatorio. Si el usuario no proporciona un valor para este parámetro al ejecutar el script, PowerShell solicitará que se ingrese uno. Si se omite, PowerShell genera un error pidiendo al usuario que proporcione el valor. HelpMessage especifica un mensaje de ayuda que se mostrará al usuario si el parámetro obligatorio no se proporciona.

 PS C:\> cat .\param.ps1
 param (
     [Parameter(Mandatory=$true, HelpMessage="Cómo te llamas?")]
     [string]$Nombre,

     [Parameter(Mandatory=$true, HelpMessage="¿En qué año naciste?")]
     [int]$Nacimiento
 )

 # Calcular la edad
 $Edad = (Get-Date).Year - $Nacimiento

 Write-Output "Hola $Nombre, Tienes $Edad"

 PS C:\> .\param.ps1 -Nombre Tutankamón -Nacimiento -1334
 Hola Tutankamón, Tienes 3358

 PS C:\> .\param.ps1 -Nombre Tutankamón
 cmdlet param.ps1 en la posición 1 de la canalización de comandos
 Proporcione valores para los parámetros siguientes:
 (Escriba !? para obtener Ayuda).
 Nacimiento: -1334
 Hola Tutankamón, Tienes 3358
 PS C:\> .\param.ps1

 cmdlet param.ps1 en la posición 1 de la canalización de comandos
 Proporcione valores para los parámetros siguientes:
 (Escriba !? para obtener Ayuda).
 Nombre: !?
 Cómo te llamas?
 Nombre: Tutankamón
 Nacimiento: -1334
 Hola Tutankamón, Tienes 3358

Evaluación de condiciones#

7 -eq 7 #True
7 -eq 8 #False
3 -gt 2 #True

Operadores lógicos#

(5 -gt 1) -And (5 -lt 10)  #True
(5 -gt 1) -And (5 -lt 10)  #True
(5 -gt 1) -Or (5 -lt 1)    #True
(5 -gt 1) -Xor (5 -lt 1)   #True
-Not (5 -lt 1)             #True

Comparación de cadenas#

"hola" -eq "hola"    #True
"hola" -eq "hoa"     #False
"hola" -ne "hoa"     #True
"hola" -ne "hola"    #False

Estructuras condicionales con if#

$numero = -10
If ($numero -gt 0) {
  echo "$numero es mayor que 0"
  }
If ($numero -gt 0) {
  echo "$numero es mayor que 0"
  }else{
  echo "$numero es negativo"
  }

 #-10 es negativo

Bucles con for#

for ($i=0;$i -lt 5;$i++){
   Write-Host $i
  }

# 0
# 1
# 2
# 3
# 4

$A = @(1, 2, 3)
for ($i = 0; $i -lt $A.Length; $i++) {
  Write-Host "Elemento $i : $($A[$i])"
  }

 # Elemento 0 : 1
 # Elemento 1 : 2
 # Elemento 2 : 3

Bucles con While#

$i = 0
While ($i -lt 5) {
echo $i
$i +=1
}

# 0
# 1
# 2
# 3
# 4

$i = 0
do {
echo $i
$i +=1
} While ($i -lt 5)

# 0
# 1
# 2
# 3
# 4

Bucles con Until#

$i = 0;
do {
   Write-Host $i
$i +=1
}
until ($i -ge 5)

# 0
# 1
# 2
# 3
# 4

Bucles con Foreach#

 $items = 0..4
 $items | ForEach-Object {
   $i="$_"
   Write-Host $i
 }

  # 0
  # 1
  # 2
  # 3
  # 4



foreach ($num in 1,2,"hola",4,5) {
echo $num
}

Archivos#

echo "usuario,grupo" > usuarios.csv
echo "user01,group01" >> usuarios.csv
echo "user02,group02" >> usuarios.csv
echo "user03,group03" >> usuarios.csv
echo "user04,group04" >> usuarios.csv
Test-Path usuarios.csv  #True ver si existe

#Leer el archivo linea a linea
foreach ($i in get-content usuarios.csv){
  echo $i
  }

#Podemos importarlo desde un csv
$A = Import-Csv -Path usuarios.csv
echo $A.usuario

#Podemos recorrer los valores
foreach ($i in  $A){
  $u=$i.usuario ; echo "usuario = $u"
  }

Funciones#

function foo($a, $b, $c) {
  "a: $a; b: $b; c: $c"
  }
foo 1 3 5
# a: 1; b: 3; c: 5

Ejemplo de función con recurrencia:

function Get-Factorial {
   param (
       [int]$n
   )

   if ($n -le 1) {
       return 1
   } else {
       return $n * (Get-Factorial -n ($n - 1))
   }
}

$number = 5
$result = Get-Factorial -n 5
Write-Output "El factorial de $number es $result"

#El factorial de 5 es 120

Windows PowerShell ISE#

../../_images/powersheelISE.png ../../_images/powersheelISE1.png ../../_images/powersheelISE2.png