1

I'm trying to read out parameters out of a ps1-file with a Powershell script. (Run with powershell inputfile.ps1 which is calling evaluation.ps1) The input file looks like this:

$a=5
$b=""
$c=
$d=555

Unfortunately it's seems impossible to detect the not existing variable 'c' with the conventional methods e.g., $null, -eq "",'', -is [string] or similar methods. This ends up that my Powershell script automatically uses the next value from variable 'd'. So in the end I get this information:

echo "$a"
5
echo "$b"

echo "$c"
555
echo "$d"
555

Is there any possibility to avoid using the value from next line or somehow detect a missing input? Unfortunately the ps1-input file should not be touched (I know when using an empty string as input like b="", all the above mentioned methods work fine).

Thanks for any help in advance.

I guess I tried all hints out of stackoverflow already here but since it's not a string but an empty input nothing works.

Di0nys0s
  • 11
  • 2
  • `$c=` is not valid code. Please share the actual parameter assignment and/or script invocation you doing or create a [mcve]. – iRon Jun 22 '23 at 15:05
  • Does this answer your question: [How to check if a PowerShell optional argument was set by caller](https://stackoverflow.com/a/48643616/1701026)? – iRon Jun 22 '23 at 15:06
  • 1
    @iRon, `$c=` automatically continues on the next line, so the whole statement - which _is_ valid - is `$c=$d=555` – mklement0 Jun 22 '23 at 21:04

1 Answers1

0

To spell it out: Your .ps1 script is malformed with respect to your intent, given that:

$c=
$d=555

despite the newline, is the same as $c=$d=555, which by design assigns 555 to both $c and $d.

You have two basic options if you want $c to be $null instead:

  • (a) Preprocess your file to replace a missing value after = with $null and then, instead of dot-sourcing it, execute the preprocessed content via Invoke-Expression

    • Note: Given that dot-sourcing and Invoke-Expression (which is generally to be avoided) allow execution of arbitrary code, be sure that you fully control or implicitly trust the script's content.
  • (b) Parse your file manually, line by line, and define the variables one by one, using Set-Variable.

Implementation of (a)

Note:

  • The assumption is that any line that ends in = is also a simple assignment statement, as shown in your question.

  • The -replace operation matches a line-ending = (optionally followed by whitespace only) and replaces it with verbatim =$null. This means that such variables will still be defined, but with value $null.

(Get-Content -Raw yourScript.ps1) -replace '(?m)=\s*$', '=$null' |
  Invoke-Expression

Implementation of (b)

Note:

  • The assumption is that your script file contains only assignment statements as shown in your question.
  • The assignment values must be literal values, not ones that require interpretation by PowerShell.
  • On the plus side, this approach prevents execution of arbitrary code.
Get-Content yourScript.ps1 |
  ForEach-Object {
    $name, $value = $_ -split '=', 2
    if ($value -eq '') { $value = $null }
    else               { $value = $value.Trim('"') }
    Set-Variable -Name $name.TrimStart('$') -Value $value
  }
mklement0
  • 382,024
  • 64
  • 607
  • 775