Home > Blockchain >  Unexpected token '}' when passing string to PowerShell script
Unexpected token '}' when passing string to PowerShell script

Time:09-22

I have a script that accepts two strings, each are delimited by '|-|'. The second string can contain any character other than '.

To call the script I do:

PowerShell .\script.ps1 -arg1 'Hello|-|World' -arg2 'random|-|dwua0928]43d}'

It raises an error on the character }. How can I resolve this?

Edit: It also has an issue with the - from the delimiters and raises the same error:

At line:1 char:54
  .\Script.ps1 -arg2 <redacted>|-|<redacted> ...    
                                 ~
Missing expression after unary operator '-'.
At line:1 char:53
  .\Script.ps1 -arg1 <redacted>|-|<redacted> ...    
                                ~
Expressions are only allowed as the first element of a pipeline.

It does that at every instance of |-|. It does it with the brackets if I change the delimiter to /-/:

At line:1 char:168
  ... <redacted>/-/<redacted>!OW}:Lj<redacted> ...
                                ~
Unexpected token '}' in expression or statement.
At line:1 char:181
  ... /-/<redacted>cO0}e]k<redacted> ...
                      ~
Unexpected token '}' in expression or statement.

The beginning of the script is this:

Param
(
    [switch] $enable,
    [string] $arg1,
    [string] $arg2
)

CodePudding user response:

  • There's generally no need to call the PowerShell CLI (powershell.exe for Windows PowerShell, pwsh for PowerShell (Core) 7 ) from inside PowerShell.

    • Assuming you're running Windows PowerShell (or, to generalize, the same edition of PowerShell), you can invoke your script directly:

      .\script.ps1 -arg1 'Hello|-|World' -arg2 'random|-|dwua0928]43d}'
      
  • If you still want to call the CLI - which is expensive, because it involves creating a child process, and also results in a loss of type fidelity - use a script block ({ ... }), but note that this works only from inside PowerShell (though it works across both PowerShell editions, i.e., you can call pwsh.exe from Windows PowerShell, and powershell.exe from PowerShell (Core) 7 )

    powershell { .\script.ps1 -arg1 'Hello|-|World' -arg2 'random|-|dwua0928]43d}' }
    
  • If you were to call from outside PowerShell, it is best to use the -File CLI parameter rather than the (implied in Windows PowerShell) -Command parameter:

    powershell -File .\script.ps1 -arg1 "Hello|-|World" -arg2 "random|-|dwua0928]43d}"
    
    • While this works from inside PowerShell too, the disadvantage compared to the { ... } approach is that the output is only ever text, whereas the { ... } approach is - within limits - capable of preserving the original data types - see this answer for more information.

    • In order to make a -Command-based command line work, enclose the PowerShell code in "..." as a whole, in which case the embedded '...' strings are passed as such:

      powershell -Command ".\script.ps1 -arg1 'Hello|-|World\' -arg2 'random|-|dwua0928]43d}'"
      

For a comprehensive overview of the PowerShell CLI, see this post.


As for what you tried:

  • You called powershell.exe with neither -File (-f) nor -Command (-c), which defaults to -Command (note that, by contrast, pwsh, the PowerShell (Core) 7 CLI, defaults to -File).

  • When -Command is used, PowerShell's command-line processing first strips all subsequent arguments of any syntactic (i.e., unescaped) " characters, namely from "..."-enclosed arguments, joins the resulting tokens with spaces, and then interprets the resulting string as PowerShell code.

  • In your case, the fact that you used '...' quoting around the arguments is irrelevant:

    • PowerShell invariably translates the original quoting into "..." quoting when calling external programs (as they can only be expected to "..." quoting, not also '...' quoting)
    • However, it only uses "..." quoting if needed, which is solely based on whether the argument at hand contains spaces.

Neither of your arguments, verbatim Hello|-|World and random|-|dwua0928]43d}, contained spaces, so they were placed as-is on the command line for powershell.exe (though note that even if they did contain spaces and had been enclosed in "..." as a result, PowerShell's command-line processing would have stripped the " chars.)

The net result was that the powershell.exe child process tried to execute the following PowerShell code, which predictably breaks with the errors shown in your question:

# !! Note the absence of quoting around the -arg1 and -arg2 values.
.\script.ps1 -arg1 Hello|-|World -arg2 random|-|dwua0928]43d}

You can easily provoke the error you saw as follows from a PowerShell session:

# -> Error "Missing expression after unary operator '-'."
Write-Output Hello|-|World
  • Related