PowerShell setting environment variable to subexpression discards newline
Question:
I have a python script:
# temp.py
print("foonbar")
I can run this in powershell:
> python .temp.py
foo
bar
I want to set the environment variable FOO
to the output of this python script. However, doing so changes the newline to a space:
> $env:FOO=$(python .temp.py)
> $env:FOO
foo bar
What I’ve Tried
Verify that environment variables can contain newlines:
> echo "foo`nbar"
foo
bar
> $env:FOO2=$(echo "foo`nbar")
> $env:FOO2
foo
bar
… so it seems like the issue has something to do with execution of a python script?
Verify that the subexpression operator $()
is not modifying the python script output:
> $(python .temp.py)
foo
bar
echo
ing the output of the python script seems to exhibit the same behavior:
> echo "$(python .temp.py)"
foo bar
… but not if I exclude the quotes:
> echo $(python .temp.py)
foo
bar
Workaround
Base64 encoding the string bypasses bypasses this issue. However, I still wonder what could be causing this?
My powershell version is 5.1.22621.963
Answers:
Use the following:
$env:FOO = (python .temp.py) -join "`n"
-
PowerShell reports stdout output from external programs such as python
line by line, which, when captured via $(...)
or (...)
, results in an array of lines (for two or more lines).
-
If you try to assign the result as-is to an environment variable – which is invariably string-typed – PowerShell implicitly stringifies the array, which means that it joins its elements with a space as the separator, so that lines foo
and bar
turn into a string with verbatim content foo bar
; that is, the newlines are replaced with spaces.
-
By explicitly joining the elements with a (LF-only) newline (expressed as "`n"
via an expandable PowerShell string) using the -join
operator, an explicit multi-line string is constructed up front, which can then be assigned to an environment variable.
I have a python script:
# temp.py
print("foonbar")
I can run this in powershell:
> python .temp.py
foo
bar
I want to set the environment variable FOO
to the output of this python script. However, doing so changes the newline to a space:
> $env:FOO=$(python .temp.py)
> $env:FOO
foo bar
What I’ve Tried
Verify that environment variables can contain newlines:
> echo "foo`nbar"
foo
bar
> $env:FOO2=$(echo "foo`nbar")
> $env:FOO2
foo
bar
… so it seems like the issue has something to do with execution of a python script?
Verify that the subexpression operator $()
is not modifying the python script output:
> $(python .temp.py)
foo
bar
echo
ing the output of the python script seems to exhibit the same behavior:
> echo "$(python .temp.py)"
foo bar
… but not if I exclude the quotes:
> echo $(python .temp.py)
foo
bar
Workaround
Base64 encoding the string bypasses bypasses this issue. However, I still wonder what could be causing this?
My powershell version is 5.1.22621.963
Use the following:
$env:FOO = (python .temp.py) -join "`n"
-
PowerShell reports stdout output from external programs such as
python
line by line, which, when captured via$(...)
or(...)
, results in an array of lines (for two or more lines). -
If you try to assign the result as-is to an environment variable – which is invariably string-typed – PowerShell implicitly stringifies the array, which means that it joins its elements with a space as the separator, so that lines
foo
andbar
turn into a string with verbatim contentfoo bar
; that is, the newlines are replaced with spaces. -
By explicitly joining the elements with a (LF-only) newline (expressed as
"`n"
via an expandable PowerShell string) using the-join
operator, an explicit multi-line string is constructed up front, which can then be assigned to an environment variable.