-1

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
)
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • 1
    How can we tell you what's wrong with the script if you don't show the script? – Jesse Sep 21 '22 at 19:09
  • 1
    Please share the complete error message (formatted as code as well, please) – Olaf Sep 21 '22 at 19:10
  • Updated it, @Olaf – Thermohalia Sep 21 '22 at 21:16
  • 1
    Do you run this command line from a PowerShell console or from a CMD? If it is the latter one use double quotes instead of single quotes. – Olaf Sep 21 '22 at 21:23
  • @Olaf: Good point in general, but with `'...'` quoting the command would have broken _differently_ from `cmd.exe`, and, conversely, `"..."` quoting (without escaping of the `"` chars.) wouldn't help, and would result in the errors shown in the question. – mklement0 Sep 22 '22 at 00:21

1 Answers1

2
  • 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
mklement0
  • 382,024
  • 64
  • 607
  • 775