【问题标题】:Piping parameter issue with powershellpowershell的管道参数问题
【发布时间】:2017-05-09 19:55:50
【问题描述】:

我遇到了一个奇怪的问题,我不知道如何解释。我希望有人能给我一些启示。

我想创建一个函数,它接受一个数组的参数,假设 $scriptnames 并且用户可以选择从以前的结果中传输它,如果他们愿意的话。我去掉了不相关的东西,以更好地说明我的困惑。

在模块的过程中,我从数组中读取每个项目并打印出来。

我的功能:

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{}

这让我感到困惑:

场景 1:

我使用此命令获取目录中的文件列表:

get-childitem | Select-Object {$_.BaseName}

文件列表正确返回,没有扩展名:

但是,当我将结果传送到我的函数时,我得到了这个打印输出:

请注意添加了不需要的 $_.BaseName= 文字。

场景 2:

但是,如果我发出这个命令:

get-childitem | Select-Object $_.BaseName

结果并没有真正过滤掉基本名称

但是当管道到我的功能时:

get-childitem | Select-Object $_.BaseName|
Get-Test -Verbose 

$_basename 文字不包括在内:

但是,基本名称包含扩展名,这让我很困惑。

有人能看到有什么东西在向你燃烧吗?以及为什么会发生以下事情

1) 为什么在场景 1 的打印输出中标记了 $_.BaseName 文字,而我没有要求这样做?

2) 为什么选择在方案 2 中似乎不起作用,但打印输出没有具有完全相同脚本的 $_.baseName?

3) 我需要在我的脚本中更正什么以仅打印不带扩展名且不带文字 $_.BaseName 的文件名?

【问题讨论】:

  • Select-Object {$_.BaseName} -> ForEach-Object {$_.BaseName}

标签: powershell


【解决方案1】:

当您包含 Select-Object BaseName 时,您将返回具有 1 个属性 BaseName 的对象数组。将其切换为Select-Object -ExpandProperty BaseName 以执行您想要的操作,或者您可以使用(Get-ChildItem).BaseName 来实现相同的结果。

每当您看到预期为字符串的内容(即Filename)时,它会作为对象/哈希表(即@{$_.BaseName=Filename})返回。如果您想让它也返回扩展名,请使用Name 而不是BaseName。如果您想要文件的完整路径,请在这种情况下使用 FullName

回答你的场景问题...

  1. 这符合预期,因为您只指定了要从对象返回的单个属性,但仍在返回对象。对象属性被命名为$_.BaseName,因为您使用调用它的方式来定义它(通常您只需要指定属性名称而不包括前面的$_. 来指示管道对象,即Select-Object BaseName)。由于场景 1 中周围的花括号,它也可以正常工作

  2. 详细文本似乎默认为 Name 属性,即使您将完整的对象传递给它。场景 2 中的第一个示例返回完整对象,因为您错误地调用 Select-Object。

  3. 我认为我最初的答案应该涵盖解决方案

【讨论】:

  • 太棒了!这就解释了!!非常感谢!
【解决方案2】:

你没有指定你是如何调用你的函数的,所以不能真正说出#1有什么问题,看起来你返回的是一个数组而不是字符串

#2 很简单。你应该简单地写

gci |select-object basename

而不是 $_.basename。

#3 可能与 2 有关。

此外,如果您尝试获取 Basename 并且不想要标头,请不要使用 Select-Object。您可以改为:

(get-childitem).basename | whatever

这是使用您上面提供的示例函数的打印方式

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

哦,您真的应该删除 Mandatory,如果您希望将内容传送到它,否则您将收到绑定错误:

Get-Test : Cannot bind argument to parameter 'scriptNames' because it is an empty string

【讨论】:

  • 我将它创建为一个Module,将它放在应该放置模块并被PS识别的地方,然后我使用Import-Module加载模块。我也尝试使用 . .\myFunction.ps1 并且它仍然具有相同的行为。我认为问题可能存在于脚本中,而不是脚本的加载方式。但是,我是 PS 新手,所以我可能会做一些我不应该做的事情。
  • 我尝试使用 basename 而不是 $_.basename 并且它仍然在做同样的事情......奇怪......
  • 我想你误会了。我指的是你称之为函数的“线”。那条线是什么?选择对象 {$_.BaseName}|你的函数?在任何情况下,您都不应该使用 {$_.baseline } 或 $_.baseline。使用我在上面提到的最后一行并输入您的函数名称而不是“whatever”。看看这是否有助于解决错误
猜你喜欢
  • 2012-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-06
  • 2014-08-30
  • 2019-04-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多