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


438

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

빠른 테스트 스크립트 :

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간에 일관된 것으로 보이므로 분명히 뭔가 잘못하고 있습니다. 누구나 정확히 무엇을 지적 할 수 있습니까?


3
다음과 같이 전화하십시오 :Test "ABC" "DEF"
Ranadip Dutta

답변:


576

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

20
마침내 내 마음에 이것을 '고정'하는 데 도움이 된 가장 중요한 것은 마지막 문장입니다.
Ashley

1
나는 마비와 쉼표로 구분하여 사용하는 것을 선호합니다. powershell에서 이것을 할 수 있습니까?
sam yi

8
@samyi 아니요 (1,2,3). 함수에 a 를 전달하는 것은 효과적으로 배열로 취급됩니다. 단일 인수. OO 메소드 스타일 인수를 사용하려면 모듈을 사용하십시오.$m = new-module -ascustomobject { function Add($x,$y) { $x + $y } }; $m.Add(1,1)
x0n

4
Powershell쉘 언어이며 쉘 언어에서 공백을 토큰 구분 기호로 사용하는 것이 일반적입니다. 내가 언급하지 않았다 Powershell여기에 다른 것, 그것은 바로 같은 다른 시스템 기본 껍질 라인에있어 cmd, sh, bash, 등
벤더 가장 중대한

270

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

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

함수 호출의 구문 함정

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

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


4
각 매개 변수를 호출하고 실제로 값을 할당하는 더 자세한 구문으로 설명합니다. 감사합니다!
ConstantineK

7
고마워, 내가 잘못하고있는 것을 이해하지 못하는 것은 나를 정신적으로 이끌었다. 내가 그것을 올바르게했을 때 나는이 행동에 대한 설명을 위해 배가 고 was 다.
BSAFH

1
답변으로 게시 해 주셔서 감사합니다. 왜 무엇이 잘못되었는지 아는 것이 무엇이 잘못되었는지도 아는 것입니다.
Gavin Ward

4
이것은 훨씬 더 나은 대답입니다. 더 올라와야합니다.
Mark Bertenshaw

53

여기에 좋은 답변이 있지만 다른 몇 가지를 지적하고 싶었습니다. 함수 매개 변수는 실제로 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임을 보증합니다. ($ _는 스크립트 블록 내부에있을 때 매개 변수를 나타냅니다.) 해당 수준이 필요한 경우 훨씬 더 큰 여러 줄의 스크립트 블록을 전달하거나 여기에서 한 것처럼 여러 스크립트 블록을 사용할 수도 있습니다. 매우 유용하고 깔끔한 기능과 직관적 인 예외를 만듭니다.


3
My_Function -NamedParamater "ParamValue"함수 호출 스타일 을 보여주기 위해 +1 가독성을 높이기 위해 더 많은 PS 스크립트 코드를 따라야하는 패턴입니다.
Mister_Tom

46

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

test "ABC" "DEF"

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

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

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


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

Test "ABC" "DEF"

11

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

Java, C ++, Ruby 및 Python은 금세기가 아니고 (C #에만 해당) 그레고리력을 가정합니다 (일부는 다른 것보다 더 많이 발전했지만).
피터 Mortensen

허. @PeterMortensen 당신의 주장은 "이 세기 나 마지막 언어에서 언어를 선택하십시오"라고 말해야한다는 것입니다. :-)
Ryan Shillington

10

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

코드 :

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
}

7

시도하면 :

PS > Test("ABC", "GHI") ("DEF")

당신은 얻는다 :

$arg1 value: ABC GHI
$arg2 value: DEF

괄호가 매개 변수를 구분한다는 것을 알 수 있습니다.


시도하면 :

PS > $var = "C"
PS > Test ("AB" + $var) "DEF"

당신은 얻는다 :

$arg1 value: ABC
$arg2 value: DEF

이제 괄호의 즉각적인 유용성을 발견 할 수 있습니다. 공백은 다음 매개 변수의 구분자가되지 않습니다. 대신 eval 함수가 있습니다.


4
Parens는 매개 변수를 분리하지 않습니다. 그들은 배열을 정의합니다.
n0rd

1
Parens는 배열을 정의하지 않고 powershell이 ​​배열로 해석 할 수있는 그룹을 정의합니다. 배열은 다음과 @같이 빈 배열처럼 선행 paren 앞에 at 기호 ( ) 로 정의됩니다 . @(); 또는 두 개의 숫자가있는이 배열 : @(1, 2).
VertigoRay

5

이것은 자주 보는 질문이므로 PowerShell 함수는 승인 된 동사 ( 함수 이름으로 Verb-Noun) 를 사용해야한다고 언급하고 싶습니다 . 이름의 동사 부분은 cmdlet이 수행하는 작업을 식별합니다. 이름의 명사 부분은 조치가 수행되는 엔티티를 식별합니다. 이 규칙 은 고급 PowerShell 사용자의 cmdlet 사용을 단순화 합니다.

또한 매개 변수가 필수 인지 여부 및 매개 변수 의 위치 와 같은 것을 지정할 수 있습니다 .

function Test-Script
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory=$true, Position=0)]
        [string]$arg1,

        [Parameter(Mandatory=$true, Position=1)]
        [string]$arg2
    )

    Write-Host "`$arg1 value: $arg1"
    Write-Host "`$arg2 value: $arg2"
}

매개 변수를 함수에 전달하려면 위치 를 사용할 수 있습니다 .

Test-Script "Hello" "World"

또는 매개 변수 이름지정 하십시오 .

Test-Script -arg1 "Hello" -arg2 "World"

당신은 괄호를 사용하지 않는 당신처럼 당신의 C #에서 함수를 호출 할 때.


두 개 이상의 매개 변수를 사용할 때는 항상 읽기 쉬운 매개 변수 이름을 전달하는 것이 좋습니다 .


참고로, 승인 된 동사 목록 링크는 더 이상 작동하지 않지만 이제 여기에서 찾을 수 있습니다 -docs.microsoft.com/en-us/powershell/developer/cmdlet/…
Keith Langmead

@KeithLangmead Keith 감사합니다. 저의 답변도 업데이트했습니다.
Martin Brandl

1
동사와 명사 모두 대문자로 "Verb-Noun"? 아마도 대답을 더 명확하게 변경 하시겠습니까?
Peter Mortensen

@PeterMortensen 언급 해 주셔서 감사합니다. 답변을 업데이트했습니다.
Martin Brandl

1
글쎄, 당신은 Get-Nodecmdlet 을 노출 고려하십시오 . 우리가 호출에 가지고 우리에게 분명한 것 Get-Node,하지 Retrieve-Node않으며 Receive-Node,도 아니다 .....
마틴 브랜들

4

함수로 무엇을하고 있는지 모르겠지만 'param'키워드 사용을 살펴보십시오. 매개 변수를 함수에 전달하는 데 약간 더 강력하고 사용자 친화적입니다. 아래는 Microsoft의 지나치게 복잡한 기사에 대한 링크입니다. 기사가 소리를내는 것만 큼 복잡하지는 않습니다.

매개 변수 사용법

또한 다음은 이 사이트에 대한 질문 의 예입니다 .

확인 해봐.


답변 해주셔서 감사합니다. 그러나 함수를 호출 할 때 문제가 발생했습니다. 함수가 param 또는 선언없이 선언되었는지는 중요하지 않았습니다.
Nasir

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

Test("ABC") ("DEF")

결과는 다음과 같이 나타납니다.

2

나는 다음을 더 일찍 언급했다.

일반적인 문제는 단수형을 사용 $arg하는 것입니다. 항상 복수형이어야합니다 $args.

문제는 아닙니다. 실제로 $arg다른 것도 가능합니다. 문제는 쉼표와 괄호를 사용하는 것이 었습니다.

작동하는 다음 코드를 실행하고 출력은 다음과 같습니다.

암호:

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

"ABC" "DEF"테스트

산출:

$var1 value: ABC
$var2 value: DEF

4
내 친구 감사합니다, 그러나 당신은 몇 년 늦었습니다 :-) 여기에 가장 큰 세 가지 답변이 문제를 충분히 해결했습니다. 답변이없는 섹션으로 이동하여 이러한 질문 중 일부를 시도해 볼 수 있습니까?
Nasir


1

다음 과 같은 함수 에서 매개 변수 를 전달할 수도 있습니다.

function FunctionName()
{
    Param ([string]$ParamName);
    # Operations
}

3
그것은 함수의 매개 변수를 정의하는 것이 었습니다. 원래 질문은 함수를 호출 할 때 매개 변수를 지정하는 방법에 관한 것이 었습니다.
Nasir

1

나는 여기에 언급 볼 수 있지만하지 않는 스플래 당신의 주장은 유용한 대안이며, (사용하는 것이 아니라 동적 명령에 인수를 구축하는 경우 특히 유용하게된다 Invoke-Expression). 위치 인수에 대한 배열과 명명 된 인수에 대한 해시 테이블로 표시 할 수 있습니다. 여기 몇 가지 예가 있어요.

배열이있는 스 플랫 (양의 인수)

위치 인수를 사용한 테스트 연결

Test-Connection www.google.com localhost

어레이 스플래 팅

$argumentArray = 'www.google.com', 'localhost'
Test-Connection @argumentArray

스플래 팅 할 때 splatted 변수를 a @대신에 참조합니다 $. Hashtable을 사용하여 표시 할 때도 동일합니다.

해시 테이블이있는 스 플랫 (명명 된 인수)

명명 된 인수를 사용한 테스트 연결

Test-Connection -ComputerName www.google.com -Source localhost

해시 테이블 스플래 팅

$argumentHash = @{
  ComputerName = 'www.google.com'
  Source = 'localhost'
}
Test-Connection @argumentHash

위치 및 명명 된 인수를 동시에 표시

위치 인수와 명명 된 인수가 모두있는 테스트 연결

Test-Connection www.google.com localhost -Count 1

배열과 해시 테이블을 함께 스플래 팅

$argumentHash = @{
  Count = 1
}
$argumentArray = 'www.google.com', 'localhost'
Test-Connection @argumentHash @argumentArray
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.