1

I can manually open up PowerShell and run

wsl
ip addr show eth0 | grep 'inet\b' | awk '{print $2}' | cut -d/ -f1

To get the IP address of the Ubuntu instance. But when I try to write a script for this (100 different ways) I always get some kind of error. This is an example

$command = "ip addr show eth0 | grep 'inet\b' | awk '{print $2}' | cut -d/ -f1"
$ip = Invoke-Expression "wsl $command"

Which gives an error about grep.

js2010
  • 23,033
  • 6
  • 64
  • 66
radop33392
  • 123
  • 7
  • As an aside: [`Invoke-Expression` (`iex`) should generally be avoided](https://stackoverflow.com/a/51252636/45375); definitely [don't use it to invoke an external program or PowerShell script](https://stackoverflow.com/a/57966347/45375). – mklement0 Jan 03 '23 at 22:05

2 Answers2

3

Call wsl.exe via the -e option and specify bash as the executable, which allows you to use the latter's -c option with a command line specified as a single string:

# Note the need to escape $ as `$ 
# to prevent PowerShell from interpolating it up front inside "..."
$command = "ip addr show eth0 | grep 'inet\b' | awk '{print `$2}' | cut -d/ -f1"

wsl -e bash -c $command

A note re the choice of string literals on the PowerShell side:

  • Using "..." quoting rather than '...' quoting is convenient if the text contains ' characters, because it obviates the need for escaping - ditto for the inverse scenario: using '...' quoting for text that contains " chars.

  • However, as in POSIX-compatible shells such as Bash, the choice of the enclosing quoting characters matters in PowerShell, because the resulting behavior differs:

    • '...' is a verbatim (single-quoted) string.

      • Unlike in POSIX-compatible shells, where escaping embedded ' chars. must be emulated with '\'', PowerShell does support direct escaping, namely with ''
    • "..." is an expandable (double-quoted) string, i.e. subject to string interpolation for substrings that start with $

      • Unlike in POSIX-compatible shells, where embedded $ chars. to be used verbatim (literally) require escaping as \$, in PowerShell you must use `$, using `, the so-called backtick, PowerShell's escape character.
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Pretty much works. What's weird is that when entering the command directly into the WSL shell or via PowerShell, I get the IP address. However with this, when I save it to a variable, I get `inet a.b.c.d` ie I for some reason I get the "inet " string as well. – radop33392 Jan 03 '23 at 23:21
  • 1
    @radop33392, escaping `$2` as `\`$2` fixes that problem, as the updated answer now explains. Without it, `$2` expands to the _empty string_, which explains the symptom. – mklement0 Jan 03 '23 at 23:29
1

Or let's assume you have powershell installed in linux (there's no Get-NetIPConfiguration?).

$command = "ip addr show eth0 | select-string inet\b | % { (-split `$_)[1] } |
   % { (`$_ -split '/')[0] }"
wsl -e pwsh -c $command

10.0.0.107

Or even without it, piping to windows powershell cmdlets.

wsl -e ip addr show eth0 | select-string inet\b | % { (-split $_)[1] } |
  % { ($_ -split '/')[0] }

10.0.0.107

$command has to be an array of words:

$command = 'ip address show eth0'
wsl -e (-split $command) | select-string inet\b | % { (-split $_)[1] } |
  % { ($_ -split '/')[0] }
js2010
  • 23,033
  • 6
  • 64
  • 66