2012-01-23 8 views
6

La siguiente secuencia de comandos PowerShell¿Por qué necesita un par adicional de soporte?

"one","two","three" | % { "$(($l++)): $_" } 

imprimirá

 
1: one 
2: two 
3: three 

Sin embargo, después de retirar el soporte alrededor $l++

"one","two","three" | % { "$($l++): $_" } 

se imprimirá

 
: one 
: two 
: three 
+0

¡Oh chico, tienes a la comunidad yendo en este! :-) –

Respuesta

12

Esto es porque $l++ es declaración voidable. En PowerShell, ciertos tipos de expresiones , cuando se usan como declaraciones, no se muestran. Las declaraciones de Voidable incluyen asignaciones y operadores de incremento/decremento. Cuando se usan en una expresión, devuelven un valor, pero cuando se usan como una declaración independiente, no devuelven ningún valor. Está muy bien explicado en Windows PowerShell en acción por Bruce Payette: operadores

El incremento y decremento casi no se incluyeron en PowerShell porque introducen un problema. En idiomas como C y C#, cuando usa uno de estos operadores como una instrucción: $ a ++ no se muestra nada. Esto se debe a que las declaraciones en C y C# no devuelven valores. Sin embargo, en PowerShell, todas las declaraciones devuelven un valor. Esto condujo a la confusión. Las personas escribiría los guiones de esta manera:

$sum=0 
$i=0 
while ($i -lt 10) { $sum += $i; $i++ } 
$sum 

y se sorprenda al ver los números del 1 al 10 que se muestra. Esto se debía a que $ a ++ devolvía un valor y PowerShell mostraba los resultados de cada instrucción. Este fue tan confuso que casi eliminamos estos operadores del idioma. Luego, acertamos con la idea de una declaración anulable. Básicamente, esto significa que ciertos tipos de expresiones , cuando se usan como declaraciones, no se muestran. Las instrucciones de Voidable incluyen las asignaciones y los operadores de incremento/decremento. Cuando se usan en una expresión , devuelven un valor, pero cuando se usan como una declaración independiente, no devuelven ningún valor. Una vez más, este es uno de esos detalles que no afectará la forma en que usa PowerShell más que para hacer que funcione como espera. (fuente: Windows Powershell en acción)

+0

La mejor respuesta del lote, creo :) – manojlds

+0

En Deep Dive, Bruce también mencionó que esto es lo que hace que las instrucciones y bucles funcionen como lo hacen: if ($ foo = Get-RandomTrueFalse) {"Esto puede ejecutarse ! "} – JasonMArcher

0

creo que hay dos tareas que tiene que hacer:

  1. Ejecutar $l++ (incremento de la variable), que sucede en el paréntesis interior
  2. recuperar el valor $l 's lo que sucede en el paréntesis exterior.

Aquí es un ejemplo de esto:

$l = 0 
"$($l++ ; $l)" 

Salidas: 1 donde

$l = 0 
"$($l++)" 

Does not nada de salida.

Para recibir la salida, necesito dos instrucciones dentro de la sub-expresión. De lo contrario, lo único que ocurre es que $l se incrementa, pero su valor no se recupera.

4

Creo que esta fue una decisión de diseño realizada por el equipo de PowerShell para evitar sorpresas debido a los valores de retorno de salida de PowerShell. Muchos usuarios de C/C# esperarían que la siguiente función solo produzca 1 no @ (0,1).

function foo { 
    $i = 0 
    $i++ 
    $i 
} 

lo tanto, el formulario de declaración $i++ no da salida al valor de $ i antes de que se incrementa. Si quieres que el comportamiento, PowerShell le permite obtener que el comportamiento poniendo la declaración de incremento (o decremento) directamente dentro de una expresión ej .:

function foo { 
    $i = 0 
    ($i++) 
    $i 
} 

Este @ es la salida (0,1).

Bruce Payette analiza esto en el Capítulo 5 de Windows PowerShell in Action 2nd Edition. Los operadores de incremento y decremento son "declaraciones anulables". Citando del libro:

Básicamente, esto significa que ciertos tipos de expresiones, cuando se usan como declaraciones , no se muestran. Las instrucciones de Voidable incluyen instrucciones de asignación y operadores de incremento/decremento. Cuando el incremento y el decremento se usan en una expresión, devuelven un valor, pero cuando se usan como una declaración independiente, no devuelven ningún valor.

1

Eso se debe a que $l++ no devuelve nada,:

$l = 0 
$l++ #nothing 
$l #gives 1 
$l++ #nothing 
($l++) #gives 2 

Esto se hace para que no haya confusión cuando regrese a la tubería. Efectivamente,

$l++ es $l = $l+ 1, por lo que no devuelve nada.

Lo que quieres ver es $l = $l + 1; $l, por eso tienes que hacer ($l++).

Cuestiones relacionadas