Аргументы командной строки в PowerShell

Введение

В PowerShell скрипт, можно передавать аргументы из командной строки. В отличие от Bash где можно просто обращаться к аргументам по порядку ($1, $2 …) в PowerShell нужно заранее создать список параметров.

param ( [тип]$имя )

param ( [string]$name, [int]$name2 )

Передаются эти аргументы указаниме имени параметра через дефис

.\demo.ps1 -name value

Примеры

bool

Следующий скрипт может принимать один аргумент типа bool. Если не передавать ничего, передать $false или 0 это будет интерпетироваться как False.

Если передать $true или любое положительное число это будет интерпретироваться как True.

Если передать строку или отрицательное число - будет ошибка.

param( [bool] $flag ) if ($flag) { Write-Output "Flag" } else { Write-Output "No flag" }

.\demo_bool.ps1 $false

No flag

.\demo_bool.ps1 $true

Flag

Пример со string и int

Следующий скрипт может принимать три именованых аргумента. Два строковых: setup, test. Один целочисленный: clean.

param ( [string]$setup, [string]$test, [int]$clean ) if ($setup -eq "ui") { python -m pip install -r setup/ui/requirements.txt } elseif ($setup -eq "full") { python -m pip install -r setup/app/requirements.txt python -m pip install -r setup/ui/requirements.txt } if ($test -eq "collect") { python -m robot app/Tests/CollectDataFromUI.robot } elseif ($test -eq "output") { python -m pytest -vvv tools/ui/verify_output.py } if ($clean -eq 1) { Remove-Item -Path "tools\data\*.csv" -Recurse -Force }

./param_demo.ps1 -setup ui ./param_demo.ps1 -setup full ./param_demo.ps1 -test collect ./param_demo.ps1 -test output ./param_demo.ps1 -clean 1

param ( [string]$test, [string]$setup, [int]$clean, [string]$path ) function setup_test_env { If ($env:VIRTUAL_ENV -eq "${PWD}\venv") { Write-Host "venv from this dir is already activated" -f Yellow Write-Host $env:VIRTUAL_ENV Write-Host "${PWD}\venv" } ElseIf ($null -ne $env:VIRTUAL_ENV) { Write-Host "WARN: venv from another dir ${env:VIRTUAL_ENV} is already activated" -f Red Write-Host $env:VIRTUAL_ENV Write-Host "${PWD}\venv" } Else { python -m venv venv .\venv\Scripts\activate python -m pip install --upgrade pip python -m pip install -r .\requirements.txt } } if ($setup -eq "testenv") { setup_test_env } elseif ($setup -eq "ui") { python -m pip install -r ui/requirements.txt } elseif ($setup -eq "full") { setup_test_env python -m pip install -r ui/requirements.txt } elseif ($test -eq "collect") { python -m robot app/Tests/CollectDataFromUI.robot } elseif ($test -eq "output") { python -m pytest -vvv ui/verify_output.py } elseif ($test -eq "static") { python ui/utils.py } elseif ($test -eq "full") { python -m robot app/Tests/CollectDataFromUI.robot python ui/utils.py python -m pytest -vvv ui/verify_output.py } else { setup_test_env } if ($clean -eq 1) { Remove-Item -Path "app\tools\data\*.csv" -Recurse -Force } if ($path -eq "tesseract") { $Env:Path += ';C:/Program Files/Tesseract-OCR' }

Проверить передан ли аргумент

Можно явно проверить существует ли переменная

param ( [string] $Url ) if (-not $Url) { Write-Output "Parameter 'Url' was not set." } else { Write-Output "Parameter 'Url' is: $Url" }

Либо с помощью $PSBoundParameters, который содержит все явно переданные аргументы.

param ( [string] $Url ) if (-not $PSBoundParameters.ContainsKey('Url')) { Write-Output "Parameter 'Url' was not set." } else { Write-Output "Parameter 'Url' is: $Url" }

.\demo.ps1 -Url aredel.com

Parameter 'Url' is: aredel.com

Если не передавать Url

.\demo.ps1

Parameter 'Url' was not set.

Аргументы по умолчанию

param поддерживает значения по умолчанию.

В таком скрипте уже нет смысла делать проверку if (-not $Url) так как мы никогда не попадём в else

param ( [string] $Url = "www.heihei.website" ) Write-Output "Parameter 'Url' is: $Url"

.\demo.ps1 -Url www.aredel.com

Parameter 'Url' is: www.aredel.com

Если не передавать Url

.\demo.ps1

Parameter 'Url' is: www.heihei.website

Проверка с $PSBoundParameters тоже не нужна, но если она остаётся - нужно понимать что именно она проверяет.

Обратите внимание, на то, что проверка с помощью $PSBoundParameters даст не такой другой результат как if (-not $Url).

param ( [string] $Url = "www.heihei.website" ) if (-not $PSBoundParameters.ContainsKey('Url')) { Write-Output "Parameter 'Url' was not set." } else { Write-Output "Parameter 'Url' is: $Url" }

.\demo.ps1 -Url www.aredel.com

Parameter 'Url' is: www.aredel.com

Если не передавать Url то мы доходим до блока else

.\demo.ps1

Parameter 'Url' was not set.

Дело в том, что хотя переменная $Url и создана со значением www.heihei.website она не присутствует в $PSBoundParameters.

$PSBoundParameters содержит явно переданные аргументы, а мы не передавали $Url

Простейший скрипт, который показывает логику работы $PSBoundParameters

param([string]$Url="www.heihei.website") "Bound? $($PSBoundParameters.ContainsKey('Url'))" "Value: $Url"

.\demo.ps1 -Url www.aredel.com

Bound? True Value: www.aredel.com

Если не передавать Url

.\demo.ps1

Bound? False Value: www.heihei.website

Автор статьи: Андрей Олегович