Powershell Объединение переменных выражений в одной командной строке - PullRequest
0 голосов
/ 06 июня 2018

Я пытаюсь понять, как Powershell обрабатывает выражения переменных в командной строке (например, в качестве параметра для командлета).Я не могу понять, как именно он анализирует выражения с участием нескольких переменных (и / или свойств переменных).Вот несколько примеров, основанных на следующих предопределенных переменных:

$a = 'abc'
$b = 'def'
$f = Get-ChildItem .\Test.txt   # assuming such a file exists in the current directory

Пример 1:

echo $a$b

Вывод: abcdef

Пример 2:

echo $a\$b

Выход: abc\def

Пример 3:

echo $f.BaseName

Выход: Test

Пример 4:

echo $a\$f.BaseName

Вывод: abc\C:\Test.txt.BaseName

В принципе, я не понимаю, почему я могу объединить две переменные (примеры 1 и 2), и я могу использовать свойства переменных (пример 3), но я не могу объединить переменныес другими переменными свойствами (пример 4).Я пробовал различные escape-последовательности (используя обратную галочку) безрезультатно.

Я понимаю, что могу сделать это, используя выражения стиля $(), например:

echo $($a + '\' + $f.BaseName)

Я просто неЯ не понимаю, почему другая форма (пример 4) недействительна - по моему мнению, она выглядит чище.

Ответы [ 2 ]

0 голосов
/ 06 июня 2018

tl; др:

Опция самая безопасная всегда использовать явные двойные кавычки для соединения аргументы , так что обычное раскрытие строки (интерполяция) правила применяются .

Применяются к вашим примерам (IЯ использую Write-Output, потому что это echo является псевдонимом в PowerShell):

Write-Output "$a$b" # example 1
Write-Output "$a\$b" # example 2
Write-Output "$a\$($f.BaseName)" # example 4 - note the required $(...)

Единственное исключение - пример 3, потому что там вы не имеете дело с аргумент, а скорее одиночное выражение :

Write-Output $f.BaseName # example 3: OK without quoting
Write-Output "$($f.BaseName)" # equivalent with double-quoting

PowerShell в основном обрабатывает составные аргументы , как если бы они были строки в двойных кавычках (то есть расширяемые), но в конечном итоге слишком много исключений , чтобы это поведение было полезным .

Эта проблема GitHub обобщает все удивительные поведения.


Что касается ваши конкретные вопросы :

Я не могу объединить переменные с othПеременные свойства (пример 4).

На самом деле, echo $a\$f.BaseName - это случай, когда составной токен неявно обрабатывается так, как если бы он был заключен в "...", и именно из-за того, что вам нужнозаключить $f.BaseName в $(...), потому что это то, что требуют правила раскрытия строки .

echo $a\$($f.BaseName)

Я понимаю, что могу сделать это, используя выражения стиля $()Например: echo $($a + '\' + $f.BaseName)

На самом деле, лучше и эффективнее просто использовать (...) в этом случае, потому что вы хотите оценить это одиночное выражение :

echo ($a + '\' + $f.BaseName)

полезный ответ briantist имеет больше различий между (...) (только для одного оператора) и $(...) (несколько операторов, с конвейерной логикой).

0 голосов
/ 06 июня 2018

Есть некоторые тонкие различия между $() и ().Я бы сказал, что в вашем примере и в большинстве случаев вы должны использовать ().

$() можно использовать, когда вам нужно что-то более сложное или выражения, которые не работают в ().Обратите внимание, что вывод $() в основном похож на вывод конвейера, поэтому некоторые вещи, которые вы можете не ожидать, произойдут.Например, посмотрите на вывод этих двух:

(1..10 -as [string[]]).GetType()
$(1..10 -as [string[]]).GetType()

Во втором случае массив [string[]] был развернут, а затем перегруппирован в тип вывода массива PowerShell по умолчанию [object[]].

См. Эту проблему GitHub для получения дополнительной информации о капризах того, как аргументы обрабатываются и анализируются, когда они не цитируются и не группируются .

...