PS shell和cmd.exe shell中的结果不同

时间:2017-10-19 22:25:10

标签: powershell cmd

此PShell代码在PS shell和cmd.exe shell中运行时似乎有不同的结果。这些运行在Windows 7 Professional上。

PS C:\src\t\rd> $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
5      0      10586  117

PS C:\src\t\rd> Get-Content .\prodlist.txt
123
456
789
345
221
PS C:\src\t\rd> Get-Content .\rd2.ps1
$orgfile = 'photo.main.jpg'
$prodfile = '.\prodlist.txt'
$replpat = '[^\.]*(.*)','$1'

Get-Content -PSPath $prodfile |
    ForEach-Object {
        $orgfile -replace $replpat | Out-Null
        Copy-Item -Path $orgfile -Destination "$_$($matches[1])" -WhatIf
    }
PS C:\src\t\rd> .\rd2.ps1
What if: Performing the operation "Copy File" on target "Item: C:\src\t\rd\photo.main.jpg Destination: C:\src\t\rd\123.main.jpg".
What if: Performing the operation "Copy File" on target "Item: C:\src\t\rd\photo.main.jpg Destination: C:\src\t\rd\456.main.jpg".
What if: Performing the operation "Copy File" on target "Item: C:\src\t\rd\photo.main.jpg Destination: C:\src\t\rd\789.main.jpg".
What if: Performing the operation "Copy File" on target "Item: C:\src\t\rd\photo.main.jpg Destination: C:\src\t\rd\345.main.jpg".
What if: Performing the operation "Copy File" on target "Item: C:\src\t\rd\photo.main.jpg Destination: C:\src\t\rd\221.main.jpg".

这是预期的结果。

但是,在cmd.exe shell中运行时,似乎$ matches变量不会保留到下一个语句中。

C:>powershell -NoProfile -Command $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
5      0      10586  117

17:12:41.25  C:\src\t\rd
C:>powershell -NoProfile -File .\rd2.ps1
Cannot index into a null array.
At C:\src\t\rd\rd2.ps1:8 char:52
+ ...        Copy-Item -Path $orgfile -Destination "$_$($matches[1])" -What ...
+                                                       ~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArray

What if: Performing the operation "Copy File" on target "Item: C:\src\t\rd\photo.main.jpg Destination: C:\src\t\rd\123".
Cannot index into a null array.
At C:\src\t\rd\rd2.ps1:8 char:52
+ ...        Copy-Item -Path $orgfile -Destination "$_$($matches[1])" -What ...
+                                                       ~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArray

What if: Performing the operation "Copy File" on target "Item: C:\src\t\rd\photo.main.jpg Destination: C:\src\t\rd\456".
...

当我转向Windows 10系统时,我在PowerShell中使用相同的失败结果:

5.1.15063..674 PS shell
5.1.15063..674 cmd.exe shell
6.0.0.beta8 PS shell

为什么$ matches变量在下一个语句中无效? 为什么在PS shell和cmd.exe shell中执行的方式不同?

2 个答案:

答案 0 :(得分:0)

我无法解释这种行为,但为什么首先采取这种错综复杂的方法呢?这样的事情会更清晰,更直接:

$pattern     = '^[^.]*'
$replacement = ''

Get-Content $prodfile | ForEach-Object {
    $suffix = $orgfile -replace $pattern, $replacement
    Copy-Item -Path $orgfile -Destination "${_}${suffix}" -WhatIf
}

或者像这样,如果你想在循环中用搜索和替换字符串定义为变量:

{{1}}

答案 1 :(得分:0)

就像@AnsgarWiechers的回答一样,这并不能解释不同PowerShell环境中的不同行为。但是,它确实展示了一些有效的方法。

核心问题是使用-replace而不是-match。使用-match会有效,但Ansgar认为这项工作最好在处理内容之前完成一次。

$orgfile = 'photo.main.jpg'
$prodfile = '.\prodlist.txt'
$replpat = '[^\.]*(.*)'

Get-Content -PSPath $prodfile |
    ForEach-Object {
        $orgfile -match $replpat | Out-Null
        Copy-Item -Path $orgfile -Destination "$_$($matches[1])" -WhatIf
    }