2017-10-19 80 views
0

在PS外壳和cmd.exe外壳中运行此PowerShell代码似乎具有不同的结果。这些运行在Windows 7 Professional上。PS外壳和cmd.exe外壳中的不同结果

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外壳中,看起来$ 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 

为什么$匹配变量不会在未来的语句是否有效? 为什么在PS shell和cmd.exe shell中执行此操作的方式不同?

回答

0

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

$suffix = $orgfile -replace '^[^.]*' 
Get-Content $prodfile | ForEach-Object { 
    Copy-Item -Path $orgfile -Destination "${_}${suffix}" -WhatIf 
} 

或者这样,如果你想与定义为变量的搜索和替换字符串循环内的替换:

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

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

目的是让事情更灵活。替换正则表达式可以产生目标可以串联在一起的任何东西。我确实认为这很容易,而且可能起作用,但那只是在这种简单的情况下。 – lit

+0

如果您将替换件移动到循环中并使用变量进行花样和替换,它应该能够完成您问题中代码的所有功能,但仍然以更清晰的方式进行。查看更新的答案。 –

+0

这并不回答不同行为的问题,但我会接受它,因为它至少在有限的情况下提供了一些可行的方法。 – lit

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 
    }