【发布时间】:2018-11-05 02:56:39
【问题描述】:
问题
我只得到PSCustomObject 类型数组中一个文件的代码行数。使用以下消息将数组错误中的所有条目恢复 -
Get-Content : 无法将参数绑定到参数“路径”,因为它为空。
在 line:42 char:100
... -Content -Path $files.UncommentedFileName) |测量-对象-线 |选择对象...
如何克服此错误并显示数组中所有文件的代码行?
约束
- 我打算将函数
Remove-VBComments重新用于必须处理VB6 文件的其他场景。因此,我无法避免定义和使用Remove-VBComments - 我打算让函数
Remove-VBComments接受流水线输入,因为它对流水线友好,以便在其他 cmdlet 可以在管道中Remove-VBComments之后运行的场景中使用 - 我在客户环境中被限制使用 PowerShell 4.0 版。
详情如下--
意图
我的代码是总结从 cmets 中剥离的 VB6 代码文件的代码行。评论始终是 single ',不提供多行 cmets。遵循 PowerShell 脚本是我实现这一意图的尝试。
PowerShell 代码
$filesToStripComment = @([PSCustomObject]@{
"SourceFileName" = ".\vb6-master\ClassTemplate\ClassBuilder\App.cls";
"UncommentedFileName" = ".\vb6-master\ClassTemplate\ClassBuilder\App.cls.uncommented"
},[PSCustomObject]@{
"SourceFileName" = ".\vb6-master\ClassTemplate\ClassBuilder\Class1.cls";
"UncommentedFileName" = ".\vb6-master\ClassTemplate\ClassBuilder\Class1.cls.uncommented"
},[PSCustomObject]@{
"SourceFileName" = ".\vb6-master\ClassTemplate\ClassBuilder\IFilterReporter.cls";
"UncommentedFileName" = ".\vb6-master\ClassTemplate\ClassBuilder\IFilterReporter.cls.uncommented"
},[PSCustomObject]@{
"SourceFileName" = ".\vb6-master\ClassTemplate\ClassBuilder\ITemplateFilter.cls";
"UncommentedFileName" = ".\vb6-master\ClassTemplate\ClassBuilder\ITemplateFilter.cls.uncommented"
});
Function Remove-VBComments {
[CmdletBinding()]
Param(
[Parameter(
Mandatory = $True,
ValueFromPipelineByPropertyName=$True
)]
[String]
$SourceFileName,
[Parameter(
Mandatory = $True,
ValueFromPipelineByPropertyName=$True
)]
[String]
$UncommentedFileName
)
Process {
(Get-Content -LiteralPath $SourceFileName) `
-replace "\'.*$",$ReplaceString -notmatch "^\s*$" `
| Out-File -LiteralPath $UncommentedFileName;
$result = [PSCustomObject]@{
SourceFileName=$($SourceFileName);
UncommentedFileName=$($UncommentedFileName)
};
Write-Output $result;
}
}
$filesToStripComment | `
Remove-VBComments -PipelineVariable "files" | `
&{Process{ `
(Get-Content -Path $files.UncommentedFileName) `
| Measure-Object -Line `
| Select-Object -Property `
@{n="FileName";e={$files.UncommentedFileName}}, `
@{n="LoC";e={$_.Lines}} `
} }
cls 文件是我从 github 项目中复制的文件。
以上代码的输出
FileName LoC
------------- -------
.\vb6-master\ClassTemplate\ClassBuilder\App.cls.uncommented 29
Get-Content : Cannot bind argument to parameter 'Path' because it is null.
At line:42 char:100
......
# The above error repeats for all other entries in the array $filesToStripComment.
观察 #1
如果我在调用 Cmdlet Remove-VBComments 后进行以下小的更改,我将获得数组 $filesToStripComment 中所有文件的 LoC 计数。
... | Remove-VBComments | Select-Object -PipelineVariable "files" | `
& { Process { (Get-Content -Path $files.UncommentedFileName) | `
Measure-Object -Line | `
Select-Object -Property @{n="FileName",e={$files.UncommentedFileName} ...
现在我不明白为什么管道
Select-Object的这种细微变化让我得到了想要的结果,但在 CmdletRemove-VBComments上使用 PipelineVariable 却没有得到结果?!
观察 #2
同时,我通过引入一个新的 Cmdlet Get-ClsFilesRecursively 即兴编写了代码,而不是传递 PSCustomObject 的数组。函数看起来像这样 -
Function Get-ClsFilesRecursively{
[CmdletBinding()]
Param(
[Parameter(
Mandatory=$True,
ValueFromPipelineByPropertyName=$True,
)]
[String]
$SourceCodePath
)
Process{
Write-Output (Get-ChildItem -Path $SourceCodePath `
-Filter "*.cls" `
-Recurse | `
Select-Object -Property `
@{n="LiteralPath";e={$_.FullName}});
}
}
要使用此功能,我会这样调用
Get-ClsFilesRecursively -SourceCodePath . -PipelineVariable "files" | `
& { Process { `
Get-Content -LiteralPath $files.LiteralPath | `
Measure-Object -Line | `
Select-Object -Property @{n="File name";e={$files.LiteralPath}} `
@{n="LoC"; e={$_.Lines}}
}}
现在这给了我目录中所有文件的代码行;无一例外。但是,此调用在文件中包含 cmets。现在,如果我在上面的调用序列中通过管道传递Remove-VBCommments,我会回到上面问题中提到的问题。
我对导致Remove-VBComments 无法与PipelineVariable 正常工作而其他Cmdlet 与PipelineVariable 正常工作的原因感到困惑!
请帮忙!
【问题讨论】:
标签: powershell pipeline powershell-4.0