Цветовое форматирование Powershell с оператором форматирования - PullRequest
1 голос
/ 05 октября 2019

Я использую оператор форматирования внутри скрипта со следующим примером:

$current = 1
$total   = 1250
$userCN  = "contoso.com/CONTOSO/Users/Adam Smith"

"{0, -35}: {1}" -f "SUCCESS: Updated user $current/$total", $userCN

Это, как ожидается, показывает следующий вывод:

SUCCESS: Updated user 1/1250 : contoso.com/CONTOSO/Users/Adam Smith

Оператор формата предназначен для сохранения целевого выходного текста на месте с текущими / итоговыми номерами, варьирующимися от 1 до 99999. Без оператора форматирования я мог бы выделить строку успеха следующим образом:

Write-Host -BackgroundColor Black -ForegroundColor Green "SUCCESS: Updated user $current/$total: $userCN"

Но вопрос в том, как использовать цвета подсветки в сочетании с оператором форматирования? Есть только параметр -f, и он не допускает параметры цвета, потому что, во-первых, это не то же самое, что Write-Host.

1 Ответ

1 голос
/ 05 октября 2019

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

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

Следовательно, Theo *Решение 1015 * из комментария является правильным:

Write-Host -BackgroundColor Black -ForegroundColor Green `
           ("{0, -35}: {1}" -f "SUCCESS: Updated user $current/$total", $userCN) 

То есть выполняется выражение -f внутри (...), и его вывод - в данном случае, одна строка - передается как позиционныйаргумент Write-Host (неявно привязывается к параметру -Object).


Обратите внимание, что вам нужно не потребность, $(...), подвыражение оператор , в данном случае.

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

# Pass a single-element array to a script block (which acts like a function).
# (...) preserves the array as-is.
PS> & { param($array) $array.GetType().Name } -array ([array] 1)
Object[]  # OK - single-element array was passed as-is

# $(...) unwraps it.
PS> & { param($array) $array.GetType().Name } -array $([array] 1)
Int32  # !! Single-element array was unwrapped.

Основное использование $(...):

  • расширение вывода из выражений или команд внутри расширяемые строки (интерполяция строк)

  • Для отправки вывода составные операторы , такие как foreach (...) { ... } и if (...) { ... } непосредственно через конвейер, после сбора выходных данных ;однако вы можете альтернативно обернуть такие операторы в . { ... } (для выполнения в той же области) или . { ... } (для выполнения в дочерней области), чтобы получить обычное поведение streaming (по одномупередача одного) в конвейере.

    • Шаг назад: учитывая, что вы уже можете использовать составные операторы в качестве выражений в присваиваниях переменных -например, $evenNums = foreach ($num in 1..3) { $num * 2 } - и выражения обычно принимаются в качестве первого сегмента конвейера - например, 'hi' | Write-Host -Fore Yellow - удивительно, что в настоящее время это не работает с составными операторами; эта проблема GitHub спрашивает, можно ли снять это ограничение.

В контексте передачи аргументов в команды :

  • Используйте $(...), оператор подвыражения только если выхотите передать выходные данные из нескольких команд или (одной или нескольких) составных операторов в качестве аргумента и / или , если выходные данные оказываются single object, вы хотите, чтобы этот объект использовался как есть, или, если это будет одноэлементный массив (перечисляемый), вы хотите, чтобы он был unrarapped (передать сам элемент, а не массив.

    • Конечно, если вы создаете аргумент string , $(...) может быть полезен внутри этой строки для строкиинтерполяция - например, Write-Host "1 + 1 = $(1 + 1)"
  • Использовать @(...), оператор подвыражения массива только если вы хотите передать выводиз нескольких команд в качестве аргумента и / или вы хотите гарантировать , что вывод становится массивом ;то есть выходные данные возвращаются в виде (обычного PowerShell) массива типа [object[]], даже если он содержит только один объект. В некотором смысле это обратное поведения $(...) в случае вывода одного объекта: оно гарантирует, что вывод одного объекта тоже станет массивом.

...