Di0nys0s
Di0nys0s

Reputation: 21

Detect empty variable in Powershell parameter list or avoid using next string input

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:

#There are also some comments
$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.

Upvotes: 2

Views: 990

Answers (1)

mklement0
mklement0

Reputation: 440037

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
  }

Upvotes: 1

Related Questions