Powershell NULL так же как и в большинстве языков обозначает пустое или неизвестное значение. Эту переменную используют для избежания ошибок, например когда мы должны быть уверены что делаем операцию с существующим значением. В других языка такое же значение несет None.
В отличие от других языков в Powershell null является переменной, обозначается как $null и хранит ссылку.
Переменная без объявленного значения будет равна неизвестному:
$null -eq $somevar
Так же как и результат функции, которая возвращает пустое значение:
function Get-None {return (Get-Process '*notexist*')}
$null -eq (Get-None)
В зависимости от того где будет применяться проверка на null результат может быть разным.
Проверка в строках
Если мы используем переменную в строках в зависимости от остального текста у нас будет либо пустая строка или пропущенное слово (в случае ниже):
$val = $null
Write-Output "Print $val val"
Такой результат является поводом экранировать переменные, когда вы пытаетесь вставить их в строки. Например если вы формируете логи и не проверяете каждое значение на NULL, то у вас может появится пустое не понятное значение. Для избежания таких ситуаций можно использовать такой подход:
$val = $null
$date = Get-Date
$error_log = "[$date] ErrorId [$val]"
Write-Output $error_log
Проверка при работе с числами
Мы можем использовать NULL и ожидать такое значение при работе с числами и не получать ошибок. В разных случаях результат будет разным:
$null -eq ($null * 7)
$null -eq (7 * $null)
$null * 7
7 * $null
Работа с массивами и индексами
Если мы объявим такую переменную и попробуем вызвать элемент по индексу, то получим ошибку:
$arr = $null
$arr[1]
- Не удается индексировать в массив
- Cannot index into a null array
Но если мы объявим массив и вызовем несуществующий элемент по индексу, то этой ошибки не будет:
$arr = '1','2','3'
$arr[100] -eq $null
Но в случаях с массивами мы можем проверять вхождение:
$arr = '1','2','3',$null
$null -in $arr
При работе с объектами
Аналогично строкам несуществующее свойство объекта тоже будет иметь неизвестное значение:
$path = Get-ChildItem
$null -eq $path.NotExist
Если мы попробуем вызвать метод, то получим ошибку:
$null.GetType()
- Невозможно вызвать метод для выражения со значением NULL
- You cannot call a method on a null-valued expression
Для избежания таких ситуация нужно делать проверки заранее или использовать try catch.
Единственное свойство, которое можно использовать - это счетчик count:
$val = $null
$val.count
0
Исключением является использование Count в PSCustomObject. В Powershell 5.1 у такого объекта нет свойства count, а начиная с версии 6 оно есть:
$value = [PSCustomObject]@{Name='SoneObject'}
if ( $value.count -eq 1 ) {"PS 6.1"}
Проверки на существование значений в условиях
В примерах с числами были ситуации, где расстановка значений играла весомое значение. Верной практикой считается ставить проверяемое значение справа, а null слева. Вы можете попробовать угадать результат следующей команды:
$value = @( $null )
if ( $value -eq $null ) {'Значение $null'}
if ( $value -ne $null ) {'Значение не $null'}
if ( $null -ne $value ) {'Значение не $null 2'}
Если бы мы не использовали третье условие, то результат был бы False и возможный скрипт бы не выполнился.
Операторы сравнения сильно зависят от контекста использования. В зависимости от того является ли левое значение скалярным (число или строка), или списком (массив, список и т.д.) у нас будут возвращаться разные значения. Для примера ситуация выше, но уже с числом вернет два True:
Если мы пишем условия, то в Powershell, так же как и в других языка, не обязательно выполнять сравнение:
$a = 1
if ($a) {'ok'}
Подобное условие на самом деле выполняет следующие операции:
if ( $null -ne $a -and
$a -ne 0 -and
$a -ne '' -and
$a -ne $false )
{
'ok'
}
В отличие от других языков в Powershell иногда можно преобразовывать $null в другие типы. Если такое преобразование будет в рамках скрипта, то они не будут равны $null:
[int]$int = $null
$int
[string]$str = $null
$str -eq ''
В других случаях у нас могут появиться ошибки:
- Не удается преобразовать значение "" в тип "System.Boolean".
- Не удается преобразовать значение в тип "System.DateTime".
[bool]$bool = $null
$bool
[datetime]$date = $null
Для проверки пустой строки можно так же использовать метод .Net IsNullOrEmpty:
$null -eq ''
[string]::IsNullOrEmpty('')
[string]::IsNullOrEmpty('some')
Работа с конвейером и циклами
При работе с конвейером, вне зависимости от заданных параметром, всегда будет ошибка:
$null | Get-NetIPAddress
- Get-NetIPAddress : Не удается проверить аргумент для параметра "AssociatedIPInterface". Аргумент имеет значение NULL. Укажите допусти мое значение аргумента, после чего повторите выполнение команды.
- Get-NetIPAddress : Cannot validate argument on parameter 'AssociatedIPInterface'. The argument is null. Provide a valid value for the
Исключения, если мы будем использовать конвейер и цикл:
$null |% {Get-NetIPAddress}
При использовании в цикле c foreach все будет пропущено:
foreach ($node in $null){Write-Output 'ok'}
А с ForEach-Object ошибка:
ForEach-Object ($node -in $null){Write-Output 'ok'}
Перенаправление вывода
Аналогично nix системам в Powershell тоже можно перенаправлять вывод в "никуда". Такую команду можно выполнять в стиле Powershell:
New-Item -Type Directory -Path 'C:\Folder' | Out-Null
Можно назначить переменную, результат будет таким же:
$null = New-Item -Type Directory -Path 'C:\Folder'
Или использовать стиль Linux:
New-Item -Type Directory -Path 'C:\Folder' > $null
Либо так, в случаях с потоками:
* > $null
...
Подписывайтесь на наш Telegram канал
Теги: #powershell