2017-10-19 23 views
0

Ce code PowerShell semble avoir des résultats différents lorsqu'il est exécuté dans le shell PS et le shell cmd.exe. Ces exécutions sont sur Windows 7 Professionnel.Résultats différents dans le shell PS et le shell 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". 

Ceci est le résultat attendu. Toutefois, dans un shell cmd.exe, il semble que la variable $ matches ne soit pas conservée dans l'instruction suivante.

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". 
... 

Quand je me tourne vers un système Windows 10, j'ai les mêmes résultats manquerais à l'aide de PowerShell:

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

Pourquoi le $ correspond à la variable non valable dans la prochaine déclaration? Pourquoi cela s'exécute-t-il différemment dans le shell PS et dans le shell cmd.exe?

Répondre

0

Je ne peux pas expliquer le comportement, mais pourquoi prendre une telle approche compliquée en premier lieu? Quelque chose comme cela serait plus clair et plus simple:

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

Ou comme si vous voulez que le remplacement dans la boucle avec la recherche et les chaînes de remplacement définies comme variables:

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

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

Le but était de rendre quelque chose de plus flexible. L'expression rationnelle de remplacement pourrait produire tout ce que la destination pourrait enchaîner. Je suis d'accord que c'est plus facile, et cela fonctionne probablement, mais c'est seulement dans ce cas simple. – lit

+0

Si vous déplacez le remplacement dans la boucle et que vous utilisez des variables pour le modèle et le remplacement, il devrait être capable de faire tout ce que le code de votre question fait, mais toujours de manière plus claire. Voir la mise à jour –

+0

Cela ne répond pas à la question des comportements différents, mais je vais l'accepter, car il présente quelque chose qui fonctionne, dans un cas limité au moins. – lit

0

Comme @AnsgarWiechers répondre, cela n'explique pas le comportement différent dans les différents environnements PowerShell. Cependant, cela montre quelque chose qui fonctionne.

Le problème principal était l'utilisation de -replace plutôt que -match. L'utilisation de -match fonctionnera, mais Ansgar a raison de dire que ce travail est mieux fait une fois avant de traiter le contenu.

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