Jak przekazać parametry do funkcji?

11

Muszę przetworzyć kopię roboczą SVN w skrypcie PS, ale mam problemy z przekazywaniem argumentów do funkcji. Oto co mam:

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] $_}

Chcę przekazać $arg[0]co $arg1do fooi $arg[1]jak $arg2. Jednak to nie działa, z jakiegoś powodu $arg1jest zawsze puste:

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>

Uwaga:"blah" parametr nie jest przekazywana jako $arg1.

Jestem absolutnie pewien, że jest to zabawnie proste (dopiero zacząłem robić PS i nadal czuję się bardzo niezdarny), ale uderzyłem się w to głową przez ponad godzinę i nie mogę nic znaleźć.

sbi
źródło

Odpowiedzi:

2

$arg[]Tablica pojawia stracić zakres wewnątrz ForEach przedmiotami .

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)"
}
Justin Dearing
źródło
Mogłem zaakceptować dowolną z trzech odpowiedzi, które do tej pory otrzymałem, ale wybiorę tę, ponieważ pokazuje to, co ostatecznie zrobiłem.
sbi
10

Powodem, dla którego $ args [0] nie zwraca niczego w obiekcie foreach, jest to, że $ args jest zmienną automatyczną, która przyjmuje polecenie bez nazwy i niedopasowane parametry do polecenia, a obiekt foreach jest nowym poleceniem. Nie ma żadnych niepasujących parametrów dla bloku procesu, więc $ args [0] ma wartość null.

Jedną rzeczą, która może pomóc, jest to, że twoje skrypty mogą mieć parametry, podobnie jak funkcje.

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 $_}

Gdy zaczniesz chcieć więcej funkcji od swoich parametrów, możesz sprawdzić post na blogu, który napisałem o postępie parametrów od $ args do aktualnych parametrów zaawansowanych, których możemy teraz używać.

Steven Murawski
źródło
Bla Powodem tego jest to, dlaczego unikam wbudowanych funkcji, takich jak Foreach-Object, na rzecz używania dobrej, surowej konstrukcji pętli foreach.
Trevor Sullivan
Ach, Ok. Teraz to rozumiem. Cholera, to wydaje się dość sprzeczne z intuicją!
sbi
3

Wypróbuj coś takiego:

# 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
}
Trevor Sullivan
źródło
To „wymuszanie zwracania elementów jako tablicy” jest czymś, co powinienem dodać. Dzięki za podpowiedź!
sbi
Tak, musisz zachować ostrożność, jeśli odzyskasz tylko jeden element - rzucając go jawnie jako tablicę, otrzymujesz spójne wyniki, dzięki czemu możesz iterować po nim za pomocą foreach.
Trevor Sullivan