Làm thế nào để truyền tham số cho một chức năng?


11

Tôi cần xử lý một bản sao làm việc SVN trong tập lệnh PS, nhưng tôi gặp khó khăn khi chuyển các đối số cho các hàm. Đây là những gì tôi có:

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

Tôi muốn vượt qua $arg[0]như $arg1để foo, và $arg[1]như $arg2. Tuy nhiên, nó không hoạt động, vì một số lý do $arg1luôn trống rỗng:

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>

Lưu ý: Các "blah"tham số không được thông qua như $arg1.

Tôi hoàn toàn chắc chắn rằng đây là một thứ gì đó cực kỳ đơn giản (tôi chỉ mới bắt đầu làm PS và vẫn cảm thấy rất vụng về), nhưng tôi đã đập đầu vào điều này trong hơn một giờ và tôi không thể tìm thấy bất cứ điều gì.

Câu trả lời:


2

Các $arg[]mảng dường như mất phạm vi bên trong 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)"
}

Tôi có thể chấp nhận bất kỳ câu trả lời nào trong số ba câu trả lời tôi nhận được cho đến nay, nhưng tôi sẽ chọn câu trả lời này, vì điều này cho thấy những gì tôi đã làm.
sbi

10

Lý do $ args [0] không trả về bất cứ thứ gì trong đối tượng foreach là vì $ args là một biến tự động lấy các tham số không tên, không khớp với một lệnh và đối tượng foreach là một lệnh mới. Không có bất kỳ tham số nào chưa từng có cho khối quy trình, vì vậy $ args [0] là null.

Một điều có thể giúp là các tập lệnh của bạn có thể có các tham số, giống như các hàm.

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

Khi bạn bắt đầu muốn có nhiều chức năng hơn từ các tham số của mình, bạn có thể muốn kiểm tra một bài đăng blog tôi đã viết về sự tiến triển của các tham số từ $ args đến các tham số nâng cao hiện tại mà chúng ta có thể sử dụng ngay bây giờ.


Blah Những lý do như thế này là lý do tại sao tôi tránh các công cụ tích hợp như Foreach-Object để sử dụng cấu trúc vòng lặp foreach thô tốt.
Trevor Sullivan

À, được rồi Điều này tôi hiểu bây giờ. Chết tiệt, điều đó có vẻ khá phản trực giác, mặc dù!
sbi

3

Hãy thử một cái gì đó như thế này:

# 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
}

Rằng "các mục buộc phải được trả lại dưới dạng một mảng" là điều tôi thực sự nên thêm vào. Cảm ơn các gợi ý!
sbi

Vâng, phải cẩn thận nếu bạn chỉ lấy lại một mục duy nhất - bằng cách chuyển nó rõ ràng thành một mảng, bạn sẽ có được kết quả nhất quán, do đó bạn có thể lặp lại nó bằng cách sử dụng foreach.
Trevor Sullivan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.