2009-12-01 4 views
9
# array 
C:\> (1,2,3).count 
3 
C:\> (1,2,3 | measure).count 
3 

# hashtable 
C:\> @{1=1; 2=2; 3=3}.count 
3 
C:\> (@{1=1; 2=2; 3=3} | measure).count 
1 

# array returned from function 
C:\> function UnrollMe { $args } 
C:\> (UnrollMe a,b,c).count 
3 
C:\> (UnrollMe a,b,c | measure).count 
1 
C:\> (1,2,3).gettype() -eq (UnrollMe a,b,c).gettype() 
True 

HashTables와의 불일치는 fairly well known이지만 official documentation은 (예를 통해) 비스듬히 언급합니다.Powershell 파이프 라인이 컬렉션을 언 롤할지 여부를 결정하는 요소는 무엇입니까?

기능에 대한 문제는 내게 뉴스입니다. 나는 지금까지 나를 물지 않았다는 것에 충격을 받았다. 스크립터가 따라야 할 지침 원칙이 있습니까? C#에서 cmdlet을 작성할 때 열거 형을 명시 적으로 제어 할 수있는 overload of WriteObject이 있지만 Posh 언어 자체에는 AFAIK와 같은 구문이 없다는 것을 알고 있습니다. 마지막 예에서 알 수 있듯이 Posh 해석기는 파이프 된 객체의 유형에 차이가 없다고 생각하는 것 같습니다. 약간의 Object 대 PSObject의 이상한 점이 있을지도 모르겠다.하지만 순수 Posh을 쓰고 스크립트 언어가 "작동하도록"기대할 때 거의 사용되지 않는다.

/편집/

키스는 내 예에서, 내가 3 개 문자열 인수보다는 하나의 문자열 [] 인수를 전달하고있어 지적하고 올바른 것입니다. 즉, Measure-Object가 Count = 1이라고 말하는 이유는 첫 번째 요소가 @ ("a", "b", "c") 인 단일 배열 배열을보고 있기 때문입니다. 공정하다. ...

# stick to single objects 
C:\> (UnrollMe a b c | measure).count 
3 

# rewrite the function to handle nesting 
C:\> function UnrollMe2 { $args[0] } 
C:\> (UnrollMe2 a,b,c | measure).count 
3 

# ditto 
C:\> function UnrollMe3 { $args | %{ $_ } } 
C:\> (UnrollMe3 a,b,c | measure).count 
3 

그러나,이 모든 것을 설명하지 않습니다 내가 연극에서 다른 규칙이있다 추정 할 수 있는지부터

# as seen earlier - if we're truly returning @(@("a","b","c")) why not count=1? 
C:\> (UnrollMe a,b,c).count 
3 

# our theory must also explain these results: 
C:\> ((UnrollMe a,b,c) | measure).count 
3 
C:\> (@(@("a","b","c")) | measure).count 
3 
C:\> ((UnrollMe a,b,c d) | measure).count 
2 

:이 지식은 여러 가지 방법으로 문제를 해결 할 수 있습니다 경우 당신은 정확하게 하나의 요소를 가진 배열을 가지고 있고 파서는 expression mode에 있고, 인터프리터는 그 요소를 "unwrap"할 것이다. 더 이상 미묘한 차이가 있습니까?

+0

WriteObject와 동일한 기능은 값이 암시 적으로 stdout 스트림으로 출력되기 때문에 거의 사용하지 않는 Write-Output cmdlet입니다. –

+0

사실 Write-Output에는 WriteObject (object, bool)처럼 -EnumerateCollection 매개 변수가 없습니다. –

+0

관련 : http://stackoverflow.com/questions/28702588/in-what-conditions-does-powershell-unroll-items-in-the-pipeline/28707054#28707054 – alx9r

답변

11

$ 인수가 풀린다는. 함수 매개 변수는 일반적으로 공백을 사용하여 전달되므로 매개 변수를 구분해야합니다. 당신이 1,2,3에 통과하면 당신은 $에 할당됩니다 세 개의 숫자의 배열은 하나의 인자를 전달하는 인수 [0] :

PS> function UnrollMe { $args } 
PS> UnrollMe 1 2 3 | measure 

Count : 3 

그룹화 내 결과 (배열) 퍼팅 표현식 (또는 서브 표현식

PS> ((UnrollMe 1,2,3) | measure).Count 
3 

동등하다 :

PS> ((1,2,3) | measure).Count 
3 

BTW 그렇지 $())는 따라서 다음 오브젝트 [] 1,2,3 UnrollMe 의해 반환 함유가 펼쳐진다 줄이기위한 다시 자격 만든다 하나의 요소가있는 배열에만 적용하면됩니다. 배열에 상관없이 당신이 그것을 어떻게 적용되는지를 여러 번에는 영향을 미치지 않습니다 이미 무언가에 배열 표현식 (@())를 사용하여

PS> ((1,2),3) | %{$_.GetType().Name} 
Object[] 
Int32 

. :-) 언 롤링을 방지하려면 쉼표 연산자를 사용하십시오. 항상 언로드 된 다른 외부 배열을 만듭니다. 당신이 이것을 실행할 때, 마지막으로

PS> (,(1,2,3) | measure).Count 
1 

: 당신이 정말로 줄이기를 방지하지 않습니다이 시나리오에서는, 당신은 단지 대신 원래의 배열 등의 풀려됩니다 외부 "래퍼"배열을 도입하여 풀기를 해결합니다 :

PS> (UnrollMe a,b,c d) | %{$_.GetType().Name} 
Object[] 
String 

넌 UnrollMe 두 항목을 리턴 것을 알 수있다 (A, B, C)와 같은 스칼라 어레이 및 D 등. 이 두 항목은 파이프 라인을 따로 따로 전송하여 결과 수가 2가됩니다.

+0

전화하세요. 명확히하기 위해 : 나의 예제에서, $ args는 배열이 아니라 배열 배열이다. 처음이자 유일한 요소는 @ (1,2,3)입니다. –

+0

흠, 추가로이 질문에 답하는 것보다 대답이 많습니다. 편집을 참조하십시오. –

+0

>> 결과 (배열)를 그룹화 표현식 (또는 하위 표현식, 예 : $())에 넣으면 결과가 언 롤링 될 수 있습니다. //// 우수 요약, 감사합니다. –

1

Measure-Object의 작동 방식과 개체가 파이프 라인을 따라 전달되는 방식과 관련이있는 것 같습니다.

당신이

1,2,3 | measure 

을 말할 때 당신이 파이프 라인에 전달 3 INT32 객체, 각 그것은 파이프 라인에보고 객체 카운트 개체를 측정을 얻을. 당신이 "를 풀다"할 때 다음과 같이

이 함수를 사용하여, 당신은 측정 개체 수가 1로, 그것은 배열의 개체를 반복하려는 시도를하지 않습니다 파이프 라인에 전달 된 하나의 배열 객체를 얻을 :

PS C:\> (measure -input 1,2,3).count 
1 

가능한 해결 방법을 "재 롤"의 foreach를 사용하여 파이프 라인 상에 배열이다

PS C:\> (UnrollMe 1,2,3 | %{$_} | measure).count 
3