[英]Piping parameter issue with powershell
I ran into a weird issue that I do not know how to explain. 我遇到了一个奇怪的问题,我不知道该如何解释。 I hope someone could shed some light for me.
我希望有人可以给我一些启发。
I would like to create a function which takes a parameter of an array, let's say $scriptnames and users have an option to pipe it from previous results should they prefer. 我想创建一个接受数组参数的函数,比如说$ scriptnames,用户可以选择从以前的结果中通过管道传递它们。 I stripped away the unrelated stuff to better illustrate my confusion.
我剥离了无关的东西,以更好地说明我的困惑。
In the process of the module, I read each item from the array and just print the item. 在模块的过程中,我从数组中读取了每个项目,然后仅打印了该项目。
My function: 我的功能:
function Get-Test
{
[CmdletBinding()]
param
(
[parameter(mandatory=$true,
ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$true)]
[string[]]$scriptNames
)
BEGIN
{
}
PROCESS
{
foreach ($scriptName in $scriptNames)
{
Write-Verbose "Executing: $scriptname"
}
}
END{}
Here was what confused me: 这就是令我困惑的地方:
Scenario 1: 方案1:
I used this command to get the list of the file in my directory: 我使用此命令来获取目录中的文件列表:
get-childitem | Select-Object {$_.BaseName}
The list of file was return correctly without extension: 文件列表已正确返回,没有扩展名:
However, when I piped the results to my function, I got this print out: 但是,当我将结果通过管道传递给函数时,我得到了以下打印内容:
Notice the unwanted $_.BaseName= literal was added. 注意,添加了不需要的$ _。BaseName =文字。
Scenario 2: 方案2:
However, if I issue this command: 但是,如果我发出以下命令:
get-childitem | Select-Object $_.BaseName
The results did not really filter out the basename only 结果并没有真正仅过滤掉基名
but when piping to my function: 但是当管道到我的职能:
get-childitem | Select-Object $_.BaseName|
Get-Test -Verbose
the $_basename literal was not included: $ _basename文字不包括在内:
However, the basename included the extension, which really confused me. 但是,基本名称包括扩展名,这确实让我感到困惑。
Can someone see something flaring up at you? 有人可以看到你身上冒出什么东西吗? and why did the following things happen :
以及为什么发生以下情况 :
1) Why was $_.BaseName literal tagged in the print out in scenario 1, which I did not ask for? 1)为什么在方案1的打印输出中标记了$ _。BaseName文字,我没有要求?
2) Why the select did not seem to work in scenario 2, but the print-out did not have $_.baseName with the exact same script? 2)为什么选择似乎在方案2中不起作用,但是打印输出没有$ _。baseName具有完全相同的脚本?
3) What do I need to correct in my script to print out the filename only without the extension and without the literal $_.BaseName? 3)我需要在脚本中更正什么才能仅输出不带扩展名且不带文字$ _。BaseName的文件名?
When you include Select-Object BaseName
, your returning an array of objects with 1 property, BaseName
. 当包含
Select-Object BaseName
,将返回具有1属性BaseName
的对象数组。 Switch it to Select-Object -ExpandProperty BaseName
to do what you're looking for, or you can use (Get-ChildItem).BaseName
to achieve the same result. 将其切换到
Select-Object -ExpandProperty BaseName
即可执行所需的操作,也可以使用(Get-ChildItem).BaseName
来获得相同的结果。
Whenever you see something expected as a string (ie Filename
) that's instead returned as an object/hashtable (ie @{$_.BaseName=Filename}
). 每当您看到期望作为字符串(即
Filename
)的东西,而是将其作为对象/哈希表(即@{$_.BaseName=Filename}
)返回时。 If you want to have it return the extension as well, use Name
instead of BaseName
. 如果要让它也返回扩展名,请使用
Name
而不是BaseName
。 If you want the full path to the file, use FullName
in that case. 如果您需要文件的完整路径,请在这种情况下使用
FullName
。
To answer your scenario questions... 要回答您的方案问题...
That behaved as expected, as you only specified a single property to be returned from the objects, but are still returning objects. 这样做的行为与预期的一样,因为您仅指定了要从对象返回的单个属性,但仍在返回对象。 The object property is named
$_.BaseName
because you defined it that way with how you called it (usually you would just need to specify the property name without including the $_.
in front to indicate the pipeline object, ie Select-Object BaseName
). 对象属性被命名为
$_.BaseName
因为您使用调用它的方式定义了它(通常,您只需指定属性名称,而无需在前面包含$_.
即可指示管道对象,即Select-Object BaseName
)。 It's also working because of the surrounding curly braces in Scenario 1 由于场景1中周围的花括号,它也起作用了
The verbose text appears to be defaulting to the Name property, even though you're passing full objects to it. 即使将完整的对象传递给它,冗长的文本似乎仍默认为Name属性。 The first example in Scenario 2 returns the full object since you're calling Select-Object incorrectly.
方案2中的第一个示例将返回完整对象,因为您未正确调用Select-Object。
My initial answer should cover the solution, I think 我认为我的最初答案应该涵盖解决方案
You did not specify how you are calling your function, so cannot really tell what's wrong with #1, it seems like you are returning an array instead of string 您没有指定如何调用函数,因此无法真正分辨#1的问题,似乎您正在返回数组而不是字符串
#2 is easy. #2很容易。 You should have simply wrote
你应该简单地写
gci |select-object basename
instead of $_.basename. 而不是$ _。basename。
#3 Probably related to 2. #3可能与2。
Also, do not use Select-Object if you are trying to get Basename and do not want the header. 另外,如果您尝试获取基本名称并且不希望使用标头,则不要使用Select-Object。 You can instead do:
您可以改为:
(get-childitem).basename | whatever
Here is how it prints with the example function you provided above 这是使用上面提供的示例功能进行打印的方式
PS C:\> (gci).basename |get-test -ver
VERBOSE: Executing: batch
VERBOSE: Executing: DB
VERBOSE: Executing: Modules
VERBOSE: Executing: nix
VERBOSE: Executing: py
VERBOSE: Executing: utils
VERBOSE: Executing: Microsoft.PowerShellISE_profile
VERBOSE: Executing: Microsoft.PowerShell_profile
VERBOSE: Executing: PowerShellTranscripts
Oh you really should remove Mandatory, if you are expecting to pipe stuff to it or you will get a binding error: 哦,如果您希望将内容强制传递给它,则应该删除Mandatory,否则会出现绑定错误:
Get-Test : Cannot bind argument to parameter 'scriptNames' because it is an empty string
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.