Яковлев


Вывод многострочного текста в PowerShell

Когда требуется вывести в консоль или в файл один блок текста, разделённый на отдельные строки, часто используется последовательный вызов командлетов Write-Host и Write-Output, каждый из которых выводит свою строку - часть общего многострочного вывода. Есть ли другие варианты? Предлагаю разобраться.

Для начала, приведу пример того, о чём сказал в самом начале - многострочный вывод текста через вызовы командлетов для каждой строки. В примере в консоль PowerShell будет выводиться сообщение “HELLO”, по одной букве на строку.

H
E
L
L
O
Write-Output 'H'; Write-Output 'E'; Write-Output 'L'; Write-Output 'L'; Write-Output 'O'

Результат выполнения кода в консоли PowerShell

Результат в консоли соответствует ожидаемому, однако при взгляде на приведённый фрагмент кода, сразу становится понятно, что его надо и можно оптимизировать. Тот же самый результат можно получить, если передать командлету Write-Output массив строк (в примере каждая строка в массива содержит только одну букву).

Write-Output 'H', 'E', 'L', 'L', 'O'

Или так, используя конвейер PowerShell.

'H', 'E', 'L', 'L', 'O' | Write-Output

Результат достигнут, но по факту сообщение в консоли всё равно формируется из отдельных строк. Цель - получить многострочный вывод из одной строки.

Символы переноса строки

Для того, чтобы разбить одно длинное сообщение в консоли на отдельные строки, следует использовать символ возврата каретки `r и символ переноса строки `n. Вместе они создадут перенос строки и переход к новой строке в многострочном сообщении.

Write-Output "H`r`nE`r`nL`r`nL`n`rO"

Символ возврата каретки и символ переноса строки можно добавить во время объединения строк в одну.

$str = 'H' + '`r`n' + 'E' + '`r`n' + 'L' + '`r`n' + 'L' + '`r`n' + 'O'
Write-Output $str

[Environment]::NewLine

В качестве альтернативы можно обратиться к свойству среды [Environment]::NewLine. В зависимости от используемой платформы, свойство возвращает символы \r\n (возврат каретки и перенос строки) для не Unix платформ или символ \n (перенос строки) для Unix платформ.

$str = 'H' + [Environment]::NewLine + 'E' + [Environment]::NewLine + 'L' + [Environment]::NewLine + 'L' + [Environment]::NewLine + 'O'
Write-Output $str

Для переносимости решения между разными платформами, использование свойства [Environment]::NewLine будет преимущественным. Для того, чтобы сократить объём кода, можно присвоить значение свойства переменной с коротким именем, затем использовать её.

$nl = [Environment]::NewLine
Write-Output ('H' + $nl + 'E' + $nl + 'L' + $nl + 'L' + $nl + 'O')

Так или иначе, все рассмотренные примеры увеличивают объём кода и усложняют его. Поэтому если в сценарии предполагается вывод объёмного блока многострочного текста, будет удобнее и проще определить, и разметить его заранее.

Here-String

Here-String - это специальная конструкция для определения многострочного строкового значения. Использование Here-String позволяет обойти все сложности, возникающие при работе с многострочными блоками текста, которые были рассмотрены выше.

Для определения многострочного строкового значения Here-String используется специальный синтаксис, включающий открывающую и закрывающую последовательность символов, размещённых на отдельных строках: @'...'@ (одиночные кавычки) или @"..."@ (двойные кавычки).

$msg = @'
Привет, пользователь!
Для продолжения работы выбери вариант:
  1. Выполнить сценарий, вывести результат в консоль;
  2. Выполнить сценарий, сохранить результат в текстовый файл;
  3. Завершить сценарий.
'@
Write-Output $msg

Пример использования синтаксиса Here-String с одинарными кавычками в PowerShell

Использование двойных кавычек в синтаксисе Here-String даёт те же возможности, что и использование двойных кавычек при работе с обычными строками PowerShell - Here-String строка становится расширяемой.

$msg = @"
Привет, $([Environment]::UserName)!
Сегодня $(Get-Date -UFormat '%d %B %Y'). До Нового года осталось $(Get-DaysBeforeNewYear) дней.
"@
Write-Output $msg

Пример использования синтаксиса Here-String с двойными кавычками в PowerShell

В этом примере используется рассмотренная ранее функция Get-DaysBeforeNewYear, при помощи которой можно быстро узнать количество дней, оставшихся до наступления Нового года.

Я настоятельно рекомендую не забывать и не принебрегать использованием Here-String в своих сценариях - это удобно, упрощает написание и чтение кода сценариев.

Какой бы вариант не выбрали вы, уверен, что теперь работа с многострочными блоками текста в сценариях, не вызовет сложностей.