Bagaimana cara melewatkan parameter ke suatu fungsi?

11

Saya perlu memproses copy pekerjaan SVN dalam skrip PS, tapi saya mengalami kesulitan menyampaikan argumen ke fungsi. Inilah yang saya miliki:

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

Saya ingin lulus $arg[0]sebagai $arg1untuk foo, dan $arg[1]sebagai $arg2. Namun, itu tidak berhasil, karena beberapa alasan $arg1selalu kosong:

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>

Catatan: The "blah"parameter tidak lulus sebagai $arg1.

Saya benar-benar yakin ini adalah sesuatu yang lucu sederhana (saya baru saja memulai dengan melakukan PS dan masih merasa sangat canggung), tetapi saya telah membenturkan kepala saya terhadap ini selama lebih dari satu jam sekarang, dan saya tidak dapat menemukan apa pun.

sbi
sumber

Jawaban:

2

The $arg[]Array tampaknya lingkup kalah dalam foreach-Obyek .

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
sumber
Saya dapat menerima salah satu dari tiga jawaban yang saya dapatkan sejauh ini, tetapi saya akan memilih yang ini, karena ini menunjukkan apa yang akhirnya saya lakukan.
sbi
10

Alasan bahwa $ args [0] tidak mengembalikan apa pun di foreach-object adalah $ args adalah variabel otomatis yang mengambil parameter yang tidak disebutkan namanya, tak tertandingi ke perintah dan objek-foreach adalah perintah baru. Tidak ada parameter yang tidak cocok untuk blok proses, jadi $ args [0] adalah nol.

Satu hal yang dapat membantu adalah skrip Anda dapat memiliki parameter, seperti fungsi.

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

Ketika Anda mulai ingin lebih banyak fungsionalitas dari parameter Anda, Anda mungkin ingin memeriksa posting blog yang saya tulis tentang perkembangan parameter dari $ args ke parameter lanjutan saat ini yang dapat kita gunakan sekarang.

Steven Murawski
sumber
Blah. Alasan seperti ini adalah mengapa saya menghindari built-in seperti Foreach-Object yang mendukung penggunaan konstruksi perulangan foreach mentah yang baik.
Trevor Sullivan
Ah, baiklah. Ini saya mengerti sekarang. Sialan, itu tampaknya sangat berlawanan dengan intuisi!
sbi
3

Coba sesuatu seperti ini:

# 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
sumber
Bahwa "memaksa item untuk dikembalikan sebagai array" adalah sesuatu yang memang harus saya tambahkan. Terima kasih atas petunjuknya!
sbi
Ya, harus hati-hati jika Anda hanya mendapatkan satu item kembali - dengan melemparkannya secara eksplisit sebagai array, Anda mendapatkan hasil yang konsisten, sehingga Anda dapat beralih menggunakan item tersebut foreach.
Trevor Sullivan