Как получить строковое представление имени переменной?

Я работаю с PowerShell, и у меня есть переменная, определенная следующим образом:

$name = "John"

Я пытаюсь найти способ получить строковое представление имени переменной, которое в данном случае будет name (без символа $).

Есть ли встроенный метод или надежный способ добиться этого в PowerShell? Я ищу решение, которое будет работать для любой переменной, а не только для этого конкретного примера.

Можете ли вы объяснить контекст? Зачем тебе это нужно? Если вы динамически ссылаетесь на переменную, посмотрите, например, этот ответ: stackoverflow.com/questions/78727803/…

Santiago Squarzon 14.07.2024 19:46
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
91
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вот простой короткий код:
Get-Variable | where 'Value' -Like $name | select -Expand 'Name'
Я намеренно использовал -Like вместо -EQ, потому что -EQ также возвращает автоматические переменные $? и $true, поскольку их значения «истина». Однако это может быть ошибкой, если ваша переменная содержит «дикий символ», например $name = "John*", поскольку она также будет возвращать такие переменные, как «johnn» и «johnm». Итак, для надежного решения вы можете использовать это:
Get-Variable | where { $name -eq $_.Value } | select -Expand 'Name'
Или:
(Get-Variable).Where({ $name -eq $_.Value }).Name

В обоих случаях следует использовать -eq, но учтите, что это не однозначное решение, поскольку одно и то же значение может содержать несколько переменных.

mklement0 14.07.2024 21:05

@mklement0 Проверьте это, и вы поймете, почему -eq в данном случае нехорошо. where 'Value' -eq $name также возвращает автоматические переменные $? и $true, поскольку их значения «истина». Чтобы код был коротким, здесь лучше использовать -like. Для того же самого резонанса, который я использовал во втором случае $name -eq $_.Value и не $_.Value -eq $name. Я много раз устранял неполадки, пока не нашел правильный краткий синтаксис.

Someone 15.07.2024 04:28

@Someone: Простой тест, показывающий, почему -like здесь не подходит: $a = 'foo'; $b = 'food'; $name = 'f*'; Get-Variable | where Value -Like $name. Однако более важным моментом является то, что ваша попытка решения по своей сути неоднозначна, независимо от того, используете ли вы -eq или -like: она не может надежно идентифицировать интересующую переменную.

mklement0 15.07.2024 04:35

@mklement0 Хорошо, это произойдет только в том случае, если в вашей переменной есть «дикий символ». Здесь это не так и встречается нечасто, в этом случае можно использовать мой второй код или Get-Variable | where { $name -eq $_.Value } | select -Expand 'Name'.

Someone 15.07.2024 04:41

@Someone: Более важный момент: ваше решение по своей сути не может однозначно идентифицировать одну переменную происхождения; по крайней мере, это ограничение должно быть заметной частью вашего ответа. Кроме того, в общем, независимо от специфики рассматриваемого случая: если вы пришли к неочевидному решению, вы должны объяснить, как вы пришли к нему, в своем ответе, чтобы будущим читателям не пришлось предполагать.

mklement0 15.07.2024 04:45

Ах, я не видел этого комментария. Могу поспорить, что у mklement0 уже есть сообщение о том, почему это происходит, я поищу его сейчас, чтобы найти ответ — здесь я учусь всю жизнь!

Bitcoin Murderous Maniac 15.07.2024 04:54

@mklement0 На мой вкус, я предпочитаю короткий код, но я обновлю свой ответ, чтобы решить вашу проблему.

Someone 15.07.2024 04:54

Я только что обнаружил, что если вы заканчиваете переменную точкой с запятой, то проблема, когда вы явно устанавливаете переменную, а затем запускаете gettype(), видя array, затем string или даже получая значения ?, $ или true на выходе, не является проблемой. Так что $name = "john";, а не это $name = "john". Я поищу еще mklement0 потрясающих ответов, чтобы найти их завтра. Я только что нашел как минимум 3 подробных сообщения и узнал больше о PS. Умопомрачительные детали!

Bitcoin Murderous Maniac 15.07.2024 05:30

Спасибо за обновление, @Someone, но ваше решение по-прежнему не является надежным по указанным причинам (несколько переменных могут содержать одно и то же значение).

mklement0 15.07.2024 12:53

@BitcoinMurderousManiac, спасибо за приятный отзыв; причина того, что что-то вроде $true -eq 'any nonempty string' есть $true, заключается в том, что RHS ([string]) приводится к типу LHS ([bool]), а приведение любой непустой строки к [bool] дает $true. Благодаря упрощенному синтаксису вы не можете контролировать порядок операндов, поэтому необходимо использовать обычный синтаксис на основе блоков сценариев.

mklement0 15.07.2024 12:56
Ответ принят как подходящий

Предполагая, что у вас есть фрагмент исходного кода, подобный описанному, вы можете использовать метод [System.Management.Automation.Language.Parser]::ParseInput(...) для его анализа, после чего вы можете выполнить поиск в результате синтаксическое дерево для выражений переменных:

# define source code literal 
$sourceCode = '$name = "John"'

# parse source code to AST
$syntaxTree = [System.Management.Automation.Language.Parser]::ParseInput($sourceCode, [ref]$null, [ref]$null)

# search for all variable expressions on the left-hand side of `=`
$variableAssignmentTargets = $syntaxTree.FindAll({
  param($childAST)

  $childAST -is [System.Management.Automation.Language.VariableExpressionAst] -and 
  $childAST.Parent -is [System.Management.Automation.Language.AssignmentStatementAst] -and 
  $childAST -eq $childAST.Parent.Left
}, $true)

# process the found expressions
$variableAssignmentTargets |ForEach-Object {
  Write-Host "Found variable with path '$($_.VariablePath)' on line $($_.Extent.StartLineNumber), position $($_.Extent.StartColumnNumber)"
}

Что в данном случае даст сообщение:

Found variable with path 'name' on line 1, position 1

Использование AST.FindAll() означает, что вы можете найти все такие назначения переменных в сложном фрагменте кода:

$sourceCode = @'
$a = 123
$b = $a + ($c = 2)
'@

# ...

Для чего мы можем ожидать вывода:

Found variable with path 'a' on line 1, position 1
Found variable with path 'b' on line 2, position 1
Found variable with path 'c' on line 2, position 12

Другие вопросы по теме