[powershell] PowerShell에서 함수에 여러 매개 변수를 전달하는 방법은 무엇입니까?

둘 이상의 문자열 매개 변수를 허용하는 함수가 있으면 첫 번째 매개 변수가 할당 된 모든 데이터를 가져 오는 것처럼 보이고 나머지 매개 변수는 빈 상태로 전달됩니다.

빠른 테스트 스크립트 :

Function Test([string]$arg1, [string]$arg2)
{
    Write-Host "`$arg1 value: $arg1"
    Write-Host "`$arg2 value: $arg2"
}

Test("ABC", "DEF")

생성 된 출력은

$arg1 value: ABC DEF
$arg2 value: 

올바른 출력은 다음과 같아야합니다.

$arg1 value: ABC
$arg2 value: DEF

이것은 여러 컴퓨터에서 v1과 v2간에 일관된 것으로 보이므로 분명히 뭔가 잘못하고 있습니다. 누구나 정확히 무엇을 지적 할 수 있습니까?



답변

PowerShell (모든 버전)에서 함수 호출의 매개 변수는 쉼표로 구분되지 않고 공백으로 구분됩니다 . 또한 괄호는 전적으로 필요하지 않으며 Set-StrictMode활성화 된 경우 PowerShell 2.0 이상에서 구문 분석 오류가 발생합니다 . 괄호로 묶은 인수는 .NET 메소드에서만 사용됩니다.

function foo($a, $b, $c) {
   "a: $a; b: $b; c: $c"
}

ps> foo 1 2 3
a: 1; b: 2; c: 3


답변

정답이 이미 제공되었지만이 문제는 미묘한 부분을 이해하려는 사람들에게 추가 세부 정보를 보증하기에 충분합니다.

나는 이것을 주석으로 추가했지만 그림을 포함하고 싶었습니다. PowerShell 함수에 대한 빠른 참조 차트에서 이것을 찢었습니다. 이것은 함수 f의 서명이 f($a, $b, $c)다음과 같다고 가정합니다 .

함수 호출의 구문 함정

따라서 공백으로 구분 된 위치 매개 변수 또는 순서 독립적 인 명명 된 매개 변수를 사용 하여 함수를 호출 할 수 있습니다 . 다른 함정은 쉼표, 괄호 공백을 인식해야 함을 나타냅니다 .

자세한 내용은 내 기사 다운 토끼 구멍 : PowerShell 파이프 라인, 함수 및 매개 변수에 대한 연구를 참조하십시오 . 이 기사에는 빠른 참조 / 벽 차트에 대한 링크도 포함되어 있습니다.


답변

여기에 좋은 답변이 있지만 다른 몇 가지를 지적하고 싶었습니다. 함수 매개 변수는 실제로 PowerShell이 ​​빛나는 곳입니다. 예를 들어 다음과 같은 고급 기능에서 이름 지정된 매개 변수 또는 위치 매개 변수를 가질 수 있습니다.

function Get-Something
{
    Param
    (
         [Parameter(Mandatory=$true, Position=0)]
         [string] $Name,
         [Parameter(Mandatory=$true, Position=1)]
         [int] $Id
    )
}

그런 다음 매개 변수 이름을 지정하여 호출하거나 위치 매개 변수를 명시 적으로 정의했기 때문에 사용할 수 있습니다. 따라서 다음 중 하나가 작동합니다.

Get-Something -Id 34 -Name "Blah"
Get-Something "Blah" 34

첫 번째 예제는 Name두 번째로 제공 되지만 매개 변수 이름을 명시 적으로 사용했기 때문에 작동합니다 . 두 번째 예는 위치에 따라 작동하므로 Name먼저해야합니다. 가능하면 항상 두 가지 옵션을 모두 사용할 수 있도록 위치를 정의하려고합니다.

PowerShell에는 매개 변수 집합을 정의하는 기능도 있습니다. 메소드 오버로드 대신에 이것을 사용하고 다시 매우 유용합니다.

function Get-Something
{
    [CmdletBinding(DefaultParameterSetName='Name')]
    Param
    (
         [Parameter(Mandatory=$true, Position=0, ParameterSetName='Name')]
         [string] $Name,
         [Parameter(Mandatory=$true, Position=0, ParameterSetName='Id')]
         [int] $Id
    )
}

이제 함수는 이름이나 ID를 취하지 만 둘 다를 취하지는 않습니다. 위치 또는 이름으로 사용할 수 있습니다. 그것들은 다른 유형이기 때문에 PowerShell은 그것을 알아낼 것입니다. 따라서이 모든 것이 작동합니다.

Get-Something "some name"
Get-Something 23
Get-Something -Name "some name"
Get-Something -Id 23

다양한 매개 변수 세트에 추가 매개 변수를 지정할 수도 있습니다. (이것은 꽤 기본적인 예였습니다.) 함수 내에서 $ PsCmdlet.ParameterSetName 속성과 함께 사용 된 매개 변수 집합을 확인할 수 있습니다. 예를 들면 다음과 같습니다.

if($PsCmdlet.ParameterSetName -eq "Name")
{
    Write-Host "Doing something with name here"
}

그런 다음 관련 참고 사항에 PowerShell의 매개 변수 유효성 검사도 있습니다. 이것은 내가 가장 좋아하는 PowerShell 기능 중 하나이며 함수 내부의 코드를 매우 깨끗하게 만듭니다. 사용할 수있는 수많은 유효성 검사가 있습니다. 몇 가지 예는 다음과 같습니다.

function Get-Something
{
    Param
    (
         [Parameter(Mandatory=$true, Position=0)]
         [ValidatePattern('^Some.*')]
         [string] $Name,
         [Parameter(Mandatory=$true, Position=1)]
         [ValidateRange(10,100)]
         [int] $Id
    )
}

첫 번째 예에서 ValidatePattern은 제공된 매개 변수가 예상 한 것과 일치하는지 확인하는 정규식을 허용합니다. 그렇지 않으면 직관적 인 예외가 발생하여 정확히 무엇이 잘못되었는지 알려줍니다. 따라서이 예에서 ‘Something’은 제대로 작동하지만 ‘Summer’는 유효성 검사를 통과하지 못합니다.

ValidateRange는 매개 변수 값이 정수에 대해 예상되는 범위 사이에 있도록합니다. 따라서 10 또는 99가 작동하지만 101은 예외를 throw합니다.

또 다른 유용한 방법은 ValidateSet이며, 허용 가능한 값의 배열을 명시 적으로 정의 할 수 있습니다. 다른 것을 입력하면 예외가 발생합니다. 다른 것들도 있지만 아마도 가장 유용한 것은 ValidateScript 일 것입니다. 여기에는 $ true로 평가되어야하는 스크립트 블록이 있으므로 하늘이 한계입니다. 예를 들면 다음과 같습니다.

function Get-Something
{
    Param
    (
         [Parameter(Mandatory=$true, Position=0)]
         [ValidateScript({ Test-Path $_ -PathType 'Leaf' })]
         [ValidateScript({ (Get-Item $_ | select -Expand Extension) -eq ".csv" })]
         [string] $Path
    )
}

이 예에서는 $ Path가 존재하는 것이 아니라 파일과 디렉토리가 아니라 파일이며 확장자가 .csv임을 보증합니다. ($ _는 스크립트 블록 내부에있을 때 매개 변수를 나타냅니다.) 해당 수준이 필요한 경우 훨씬 더 큰 여러 줄의 스크립트 블록을 전달하거나 여기에서 한 것처럼 여러 스크립트 블록을 사용할 수도 있습니다. 매우 유용하고 깔끔한 기능과 직관적 인 예외를 만듭니다.


답변

괄호없이 구분 기호로 쉼표를 사용하지 않고 PowerShell 함수를 호출합니다. 다음을 사용하십시오.

test "ABC" "DEF"

PowerShell에서 쉼표 (,)는 배열 연산자입니다. 예 :

$a = "one", "two", "three"

$a세 개의 값을 가진 배열로 설정 됩니다.


답변

Function Test([string]$arg1, [string]$arg2)
{
    Write-Host "`$arg1 value: $arg1"
    Write-Host "`$arg2 value: $arg2"
}

Test "ABC" "DEF"


답변

C # / Java / C ++ / Ruby / Python / Pick-A-Language-From-This-Century 개발자이고 항상 수행 한 작업이므로 쉼표로 함수를 호출하려는 경우 무언가가 필요합니다. 이처럼 :

$myModule = New-Module -ascustomobject {
    function test($arg1, $arg2) {
        echo "arg1 = $arg1, and arg2 = $arg2"
    }
}

이제 전화 :

$myModule.test("ABC", "DEF")

그리고 당신은 볼 수 있습니다

arg1 = ABC, and arg2 = DEF


답변

함수에 몇 개의 인수를 전달할지 모르는 경우에도 다음과 같은 매우 간단한 접근 방식을 사용할 수 있습니다.

코드 :

function FunctionName()
{
    Write-Host $args
}

그것은 모든 논쟁을 인쇄 할 것입니다. 예를 들면 다음과 같습니다.

FunctionName a b c 1 2 3

산출

a b c 1 2 3

많은 (선택적) 매개 변수를 가질 수 있지만 구문 오류 등에 대한 피드백을 제공하기 위해 해당 명령을 사용하는 외부 명령을 사용하는 함수를 만들 때 특히 유용합니다.

여기 또 다른 실제 예가 있습니다 (추적 된 이름을 기억하는 것을 싫어하는 tracert 명령에 대한 함수 작성).

코드 :

Function traceroute
{
    Start-Process -FilePath "$env:systemroot\system32\tracert.exe" -ArgumentList $args -NoNewWindow
}