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.