2
for ($i=1; $i -lt 3; $i++){
$tT=$i
$ExecutionContext.InvokeCommand.ExpandString($o0)
echo $o0
echo $tT
}

$o0="weird${tT}";

outputs: weird2 weird2 1 weird2 weird2 2

why is that? I'd expect

weird1 weird1 1 weird2 weird2 2

how can I make things work?

mklement0
  • 382,024
  • 64
  • 607
  • 775
yBother
  • 648
  • 6
  • 25
  • 2
    You only define `$o0` _after_ having run the loop, and it doesn't contain anything that could be expanded (because you're using `"` double-quotes, the parser has already expanded `${tT}` for you). What exactly are you hoping to accomplish? – Mathias R. Jessen Jan 19 '22 at 11:58

3 Answers3

1

The incidental problem with your code is that you're defining your string template, $o0, only after you're trying to use it.

  • This problem was masked by the ISE's unfortunate behavior of effectively dot-sourcing script invocations. i.e. executing them in the same scope during repeated invocations, which can have side effects.

  • As an aside: The PowerShell ISE is no longer actively developed and there are reasons not to use it (bottom section), notably not being able to run PowerShell (Core) 6+. The actively developed, cross-platform editor that offers the best PowerShell development experience is Visual Studio Code with its PowerShell extension.

The conceptual problem with your code is that you're mistakenly using an expandable (double-quoted) string ("...") to define your string template, which results in instant expansion (interpolation).

The point of using $ExecutionContext.InvokeCommand.ExpandString() is to pass it a string value with unexpanded variable references or subexpressions, in order to expand them on demand, with the then-current variable values and expression results.

To create such an unexpanded string value, you need a verbatim (single-quoted) string ('...').

Therefore, your code should be:

# Define the string template
# *as a verbatim string*, i.e. *single-quoted*
$o0='weird${tT}'

for ($i=1; $i -lt 3; $i++) {
  # (Re)define $tT
  $tT=$i
  # Use on-demand expansion of the value of $o0,
  # which uses the current value of $tT
  $ExecutionContext.InvokeCommand.ExpandString($o0)
}

Output:

weird1
weird2
mklement0
  • 382,024
  • 64
  • 607
  • 775
0

Your current loop doesn't change the content of $o0. If you execute your code in a clean PS session it will only output empty lines followed by one and two. As only $tT has a value.

You'd need to include $o0 in your loop to actualy print that during runtime.

for ($i=1; $i -lt 3; $i++){
    $tT=$i
    $o0="weird${tT}";
    echo $o0
    echo $tT
}

The $ExecutionContext.InvokeCommand.ExpandString($o0) isn't all that useful with what you currently have.

Seth
  • 1,215
  • 15
  • 35
0

actually I was tricked by Powershell ISE. Apparently "Run Script" does not clear previous context thats why output can be very misleading. The correct output of the mentioned script would actually not contain "weird2" but only "1" and "2" as Seth pointed out.

yBother
  • 648
  • 6
  • 25