Come passare i parametri a una funzione?


11

Devo elaborare una copia di lavoro SVN in uno script PS, ma ho problemi a passare argomenti alle funzioni. Ecco cosa ho:

function foo($arg1, $arg2)
{
  echo $arg1
  echo $arg2.FullName
}

echo "0: $($args[0])"
echo "1: $($args[1])"
$items = get-childitem $args[1] 
$items | foreach-object -process {foo $args[0] $_}

Voglio passare $arg[0]come $arg1a foo, e $arg[1]come $arg2. Tuttavia, non funziona, per qualche motivo $arg1è sempre vuoto:

PS C:\Users\sbi> .\test.ps1 blah .\Dropbox
0: blah
1: .\Dropbox
C:\Users\sbi\Dropbox\Photos
C:\Users\sbi\Dropbox\Public
C:\Users\sbi\Dropbox\sbi
PS C:\Users\sbi>

Nota: il "blah"parametro non viene passato come $arg1.

Sono assolutamente sicuro che sia qualcosa di esilarantemente semplice (ho appena iniziato a fare PS e mi sento ancora molto maldestro), ma ho sbattuto la testa contro questo per più di un'ora e non riesco a trovare nulla.

Risposte:


2

L' $arg[]array sembra perdere l'ambito all'interno di ForEach-Object .

function foo($arg1, $arg2)
{
  echo $arg1
  echo $arg2.FullName
}

echo "0: $($args[0])"
echo "1: $($args[1])"
$zero = $args[0]
$one = $args[1]
$items = get-childitem $args[1] 
$items | foreach-object {
    echo "inner 0: $($zero)"
    echo "inner 1: $($one)"
}

Potrei accettare una delle tre risposte che ho ricevuto finora, ma sceglierò questa, perché questo mostra cosa ho finito per fare.
— sabato

10

Il motivo per cui $ args [0] non sta restituendo nulla nell'oggetto foreach è che $ args è una variabile automatica che accetta parametri senza nome e senza eguali in un comando e l'oggetto foreach è un nuovo comando. Non ci sono parametri senza eguali per il blocco di processo, quindi $ args [0] è nullo.

Una cosa che può aiutare è che i tuoi script possono avere parametri, proprio come le funzioni.

param ($SomeText, $SomePath)
function foo($arg1, $arg2)
{
  echo $arg1
  echo $arg2.FullName
}

echo "0: $SomeText"
echo "1: $SomePath"
$items = get-childitem $SomePath
$items | foreach-object -process {foo $SomeText $_}

Quando inizi a desiderare più funzionalità dai tuoi parametri, potresti voler dare un'occhiata a un post sul blog che ho scritto sulla progressione dei parametri da $ args agli attuali parametri avanzati che possiamo usare ora.


Blah. Ragioni come questa sono le ragioni per cui evito i built-in come Foreach-Object a favore dell'utilizzo del buon vecchio costrutto di loop foreach grezzo.
— Trevor Sullivan,

Ah ok. Questo lo capisco ora. Dannazione, sembra abbastanza controintuitivo, però!
— sabato

3

Prova qualcosa del genere:

# Use an advanced function
function foo
{
  [CmdletBinding()]
  param (
      [string] $arg1
    , [string] $arg2
  )

  Write-Host -Object $arg1;
  Write-Host -Object $arg2;
}

# Create array of "args" to emulate passing them in from command line.
$args = @('blah', 'c:\test');

echo "0: $($args[0])"
echo "1: $($args[1])"

# Force items to be returned as an array, in case there's only 1 item returned
$items = @(Get-ChildItem -Path $args[1]);
Write-Host -Object "There are $($items.Count) in `$items";

# Iterate over items found in directory
foreach ($item in $items) {
    foo -Arg1 $args[0] -Arg2 $item.FullName
}

Che "forzare gli articoli a essere restituiti come un array" è qualcosa che dovrei davvero aggiungere. Grazie per il suggerimento!
— sabato

Sì, bisogna fare attenzione se si ottiene indietro solo un singolo elemento: eseguendo il cast esplicitamente come un array, si ottengono risultati coerenti, in modo da poter iterare su di esso utilizzando foreach.
— Trevor Sullivan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.