Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.3k views
in Technique[技术] by (71.8m points)

powershell - Is it possible to print variable names?

Is it possible to print variable names in PowerShell?

$myVariable = "My Value"
Write-Host "The variable name is ?????"

Expected output:

The variable name is myVariable

Question 2 (more tricky): Is it possible to print variable name passed to a function in PowerShell?

Function MyFunc($myArg){
   Write-Host "The variable name is ?????"
}

$myVariable = "My Value"
MyFunc $myVariable

Expected output:

The variable name is myVariable

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

No!

(at least not in a reliable fashion)

The simple reason being that contextual information about a variable being referenced as a parameter argument will have been stripped away by the time you can actually inspect the parameter value inside the function.

Long before the function is actually called, the parser will have evaluated the value of every single parameter argument, and (optionally) coerced the type of said value to whatever type is expected by the parameter it's bound to.

So the thing that is ultimately passed as an argument to the function is not the variable $myVariable, but the (potentially coerced) value of $myVariable.

see the about_Parsing help file (Get-Help about_Parsing) for more on this topic


It's maybe also worth noting that there's no guarantee that a parameter argument is a variable and not a literal or another value expression:

PS C:> MyFunc 'This is not even a variable'
PS C:> MyFunc $('Neither','is','this' -join ' ')

You can get some information about (potentially) used variables, by looking at the calling context, retrieved through the Get-PSCallStack cmdlet:

function Get-ImmediateInvocationString
{
    param($myArg)

    # Grab second-to-last call
    return @(Get-PSCallStack)[-2].InvocationInfo.Line
}

Then use it like:

PS C:> $myVariable = "someValue"
PS C:> Get-ImmediateInvocationString -myArg $myVariable
Get-ImmediateInvocationString -myArg $myVariable

You could (ab)use this to infer the argument to -myArg, by say grabbing the last "variable-like" string in the invocation:

function Get-ImmediateInvocationString
{
    param($myArg)

    # Grab second-to-last call
    $Line = @(Get-PSCallStack)[-2].InvocationInfo.Line
    if($Line -match '$(?<varName>[w]+)s*$'){ 
        Write-Host $Matches['varName'] 
    }
}

This may seem like it works great at the onset:

PS C:> Get-ImmediateInvocationString -myArg $myVariable
myVariable

Until a user who doesn't care about your conformance expectations comes along:

PS C:> Get-ImmediateInvocationString -myArg $myVariable; $lol = ""; Write-Host $lol
lol

So no, you can't do what you want without parsing the calling expression in the same fashion as the actual parser does.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...