Перейти к содержимому

Как подставлять значения переменных в строках с Powershell

В Powershell есть много методов работы со строками. Один из самых популярных способов — это использование переменных в строках с последующей подменой. Такой метод часто называют подстановкой или форматированием. В этой статье будут рассмотрены все способы таких операций на примерах.

Сложение

Самый простой способ сложения значения переменной и строки относится к конкатенации. Мы просто используем знак сложения:

$name = 'Алексею'
$mail = 'Отправить сообщение ' + $name

Такой же способ сработает с числом и несколькими переменными:

$name = 'Алексею'
$subject = 'Отправить сообщение '
$time = 13
$mail = $subject + $name + ' ' + $time

Подстановка переменных

Самый удобный способ подстановки переменных — это их использование в строках. Именно этот способ несет основное отличие между одинарными и двойными кавычками. Если мы будем подставлять переменную с одинарными кавычками — значение будет интерпретироваться как просто строка.

$year = '2019'
$text = "Сотрудник родился в $year году"

Команды

Такой способ подстановок мы можем использовать и для команд, но при вызове свойств или методов можем получить некорректные данные:

$date = Get-Date
$message = "Мы живем в $date.year году"

Такая ошибка происходит из-за интерпретации точки рядом с переменной. Powershell относит эту точку к продолжению строке. Способ обойти эту проблему — использование скобок (аналогичное можно сделать и в Bash):

$date = Get-Date
$message = "Мы живем в $($date.year) году"

Используя этот способ мы можем и вызывать команды аналогично следующему примеру:

$message = "Последний HotFix был установлен $((Get-HotFix | select -First 1).InstalledOn)"

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

При попытке выполнения следующей подстановки мы не получим ожидаемый результат:

$end = 'от'
Write-Host "Зол$endая"

В примере выше просто нельзя идентифицировать начало и конец переменной. Для исправления таких ситуаций мы можем использовать фигурные скобки, а так же  и методы описанные выше:

$end = 'от'
Write-Host "Зол${end}ая"
Write-Host "Зол$($end)ая"

Отложенное развертывание значений переменных

Если мы используем переменную в строке до ее объявления мы получим, отчасти, пустой ответ:

$text = "Directory: $dir"
$dir = "C:"

Метод .NET .InvokeCommand.ExpandString позволяет выполнить замену переменной до объявления строки в которой она находится. Основная проблема работы с этим методом в том, что он работает в рамках видимости переменных. Мы должны будем передать методу только строку, которую захотим использовать:

$text = "Directory: $dir"
$dir = "C:"
$result = $ExecutionContext.InvokeCommand.ExpandString($text)

Форматирование

Форматирование — это еще один способ подстановки значений. Мы можем использовать методы как Powershell, так и .NET:

# Метод Powershell
'Размер диска {0}Gb. Использовано {1}Gb' -f '10','8'

# Метод .Net
[string]::Format('Размер диска {0}Gb. Использовано {1}Gb', '10','8')

Для подстановки значений используются массивы (в случае выше это массив из 10 и 8). Первое значение массива имеет индекс, который равен 0. Сам индекс — это порядок нумерации и в большинстве языков он начинается с 0. Когда в строках мы указываем {0} мы буквально говорим, что оно будет равно первому значению массива. 

Аналогично пример, но тут мы пропустим одно значение с индексом 1:

$array = @('10Gb', 'Неиспользуемое значение', '8Gb')
'Размер диска {0}. Использовано {2}' -f $array

Есть так же встроенные методы форматирования, которые позволяют преобразовать значения внутри строки. Например мы можем изменить формат даты с в вид день-месяц-число:

# Смотрим формат вывода даты
Get-Date
# Преобразуем дату внутри
"{0:dd-MM-yyyy}" -f (Get-Date)

Преобразование данных в строки

Вам может понадобится преобразовать массив в строку. Для таких операций, во многих языках, существует оператор join. Единственное что мы должны указать — это разделитель, который будет использоваться для создания строки:

$array = @('Я', 'пошел', 'на работу')
$array -join ' '

В примере выше был использован пробел в качестве разделителя, так как именно пробелы сделают предложения читаемым. Так же часто бывает нужно использовать запятые ‘,’ или знак обозначающий перенос строк «`n». Перенос строк используется чаще всего там, где планируется импорт и экспорт файлов и тут так же важен тип кавычек:

$array = @('Я', 'пошел', 'на работу')
$array -join "`n"

Преобразовать массив в строку, не указывая разделителя, так же можно использовав метод .Net:

$letters = @('a','b','c')
[string]::Concat($letters)

Строки — это бывшие массивы

Если посмотреть поверхностно на пример ниже, то мы увидим только скрипт добавляющий случайные значения к строке:

$str = "Случайные числа: "
foreach ($num in 1..10){
 $random_num = Get-Random -Minimum 1 -Maximum 100
 $str += ' '+$random_num 
}

На самом деле, при каждой итерации (цикле), у нас создается массив из 2 элементов, а затем он объединяется. Минус такого подхода в том, что объединение происходит каждую итерацию, а не единожды. Такой минус будет ощутим при больших данных. Если для вас этот момент важен — вы можете использовать класс .NET StringBuilder, который объединит значения только после цикла:

# Создаем объект класса
$net_class = New-Object -TypeName "System.Text.StringBuilder"
# Добавляем к нему первую строку
[void]$net_class.Append("Случайные числа: ")
foreach ($num in 1..10){
 $random_num = Get-Random -Minimum 1 -Maximum 100
 # Добавляем в объект класса случайное значение
 [void]$net_class.Append("$random_num ")
}
# Используем метод для объединения всех значений
$str =$net_class.ToString()

Преобразование путей

При работе с путями мы так же используем строки. Есть командлет, который позволяет соединять части путей:

$directory = 'System32'
Join-Path -Path 'C:Windows' -ChildPath $directory

Плюс этой команды в том, что он будет работать с любыми видами слэшей преобразовывая их в корректный формат:

Поиск и замена

Основной способ замены значений в строках — это использование параметра ‘-replace’:

$job = 'Зовите меня Димон'
$job -replace 'Димон','Вован'

Если вы используете какие-то шаблоны для конфигурации сервисов хороший способ автоматизировать этот процесс — использовать явные идентификаторы, например «#IPADDRESS#». При надобности вы сможете найти это значение в тексте и заменить его:

$job = '
ipaddr: #IPADRESS#
DNS1: #DNS1#
'
$job -replace '#IPADRESS#','192.168.3.1' -replace '#DNS1#','8.8.8.8'

Еще один из способов такой подстановки — использование хэш таблиц (массив из ключей и значений). Такой способ подойдет, если вы используете множество идентификаторов. Мы объявляем хэш таблицу с нужными значениями, а через цикл проходим и применяем их к тексту:

$hash_table = @{
    IPAddress='192.168.3.2';
    DNS1='8.8.8.8';
    Gateway='192.168.3.1';
}

$job = '
ipaddr: #IPADDRESS#
DNS1: #DNS1#
GATE: #Gateway#
'

foreach($value in $hash_table.GetEnumerator()){
  $ff = '#{0}#' -f $value.key
  $job = $job -replace $ff, $value.Value
}

Опубликовано вPowershell

Ваш комментарий будет первым

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *