简体   繁体   English

Powershell的管道参数问题

[英]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... 要回答您的方案问题...

  1. 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中周围的花括号,它也起作用了

  2. 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。

  3. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM