2017-10-19 99 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 
    }