Як обробити аргументи командного рядка в PowerShell


494

Який "найкращий" спосіб обробляти аргументи командного рядка?

Схоже, є кілька відповідей на те, що таке "найкращий" спосіб, і в результаті я застряг у тому, як впоратися з чимось простим, як:

script.ps1 /n name /d domain

І

script.ps1 /d domain /n name.

Чи є плагін, який може впоратися з цим краще? Я знаю, що тут винаходити колесо.

Очевидно, що я вже не є гарним і, безумовно, не є "найкращим", але це працює .. і це НЕГОЛОЖНО.

for ( $i = 0; $i -lt $args.count; $i++ ) {
    if ($args[ $i ] -eq "/n"){ $strName=$args[ $i+1 ]}
    if ($args[ $i ] -eq "-n"){ $strName=$args[ $i+1 ]}
    if ($args[ $i ] -eq "/d"){ $strDomain=$args[ $i+1 ]}
    if ($args[ $i ] -eq "-d"){ $strDomain=$args[ $i+1 ]}
}
Write-Host $strName
Write-Host $strDomain

Відповіді:


917

Ви винаходите колесо. Нормальні сценарії PowerShell мають параметри, починаючи з -, наприкладscript.ps1 -server http://devserver

Потім ви обробляєте їх у paramрозділі на початку файлу.

Ви також можете призначити параметри за замовчуванням для своїх параметрів, прочитати їх з консолі, якщо вони відсутні, або зупинити виконання сценарію:

 param (
    [string]$server = "http://defaultserver",
    [Parameter(Mandatory=$true)][string]$username,
    [string]$password = $( Read-Host "Input password, please" )
 )

Всередині сценарію можна просто

write-output $server

оскільки всі параметри стають змінними, доступними в області скрипту.

У цьому прикладі значення $serverотримує значення за замовчуванням, якщо скрипт викликається без нього, скрипт зупиняється, якщо ви опускаєте -usernameпараметр, і просить ввести термінал, якщо -passwordпропущено.

Оновлення: Ви також можете передати "прапор" (булевий параметр true / false) до сценарію PowerShell. Наприклад, ваш скрипт може прийняти "силу", коли сценарій працює в більш обережному режимі, коли сила не використовується.

Ключове слово для цього - [switch]тип параметра:

 param (
    [string]$server = "http://defaultserver",
    [string]$password = $( Read-Host "Input password, please" ),
    [switch]$force = $false
 )

Всередині сценарію тоді ви працюєте з ним так:

if ($force) {
  //deletes a file or does something "bad"
}

Тепер при виклику скрипту слід встановити параметр switch / flag таким чином:

.\yourscript.ps1 -server "http://otherserver" -force

Якщо ви прямо хочете заявити, що прапор не встановлений, для цього є спеціальний синтаксис

.\yourscript.ps1 -server "http://otherserver" -force:$false

Посилання на відповідну документацію Microsoft (для PowerShell 5.0; версії 3.0 та 4.0 також доступні за посиланнями):


58
Дійсно, однією з великих переваг PowerShell є те, що вона забезпечує стандартну інфраструктуру для розбору параметрів, яка є простою у використанні.
Кіт Хілл

14
@naivists з PowerShell 2.0 замість [string]$username = $(throw "-username is required.")є синтаксис обов'язкових параметрів: [Parameter(Mandatory=$true)][string]$username. Ось більш детальну інформацію про різницю між цими методиками: blogs.technet.com/b/heyscriptingguy/archive/2011/05/22/…
v.karbovnichy

7
Остерігайтеся помилки, коли аргумент не надається; powershell просто захопить будь-який додатковий текст з командного рядка:. \ yourscript.ps1 -server " serv " -password "mypass" typo Це магічно призначить "typo" $ username.
sheamus

4
Використання блоку парам, мабуть, має й інші ненавмисні наслідки: stackoverflow.com/questions/40940819/…
Логан

1
@sheamus: це не помилка! Powershell буде обробляти та призначати аргументи в тому порядку, який їм задано, якщо тільки це не буде відмінено за допомогою правильної назви параметра, наприклад, якщо ваш парам-блок перелічено: $ user $ pass $ server, і ви виконайте свойcript.ps1 abc, a буде встановити в $ user, b в $ pass і c в $ server, ПІДНЯТЬ, що ви спеціально їх призначите! Отже, якщо ви скажете: yourscript.ps1 -pass abc, $ pass буде встановлено на a, а інші (безіменні) параметри будуть використані для заповнення відсутніх у порядку, зазначеному в блоці параметрів, так що $ user = b, $ сервер = c.
Фернандо Мадруга
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.