Каковы некоторые из наиболее полезных, но малоизвестных функций языка PowerShell - PullRequest
28 голосов
/ 21 мая 2009

Некоторое время назад я читал о назначениях с несколькими переменными в PowerShell. Это позволяет вам делать такие вещи

64 >  $a,$b,$c,$d = "A four word string".split()

65 >  $a
A

66 >  $b
four

Или вы можете поменять местами переменные в одном выражении

$a,$b = $b,$a

Какие малоизвестные самородки PowerShell вам встречались, и вы думаете, что они не так известны, как следовало бы?

Ответы [ 10 ]

19 голосов
/ 25 мая 2009

На сегодняшний день самой мощной функцией PowerShell является его поддержка ScriptBlock . Тот факт, что вы можете так кратко обойти фактически анонимные методы без каких-либо ограничений типов, примерно такой же мощный, как указатели на функции C ++, и такой же простой, как лямбда-символы C # или F #.

Я имею в виду, как круто, что с помощью ScriptBlocks вы можете реализовать выражение «с помощью» (которого у PowerShell нет по своей природе). Или, до v2 вы могли бы даже реализовать try-catch-finally .

function Using([Object]$Resource,[ScriptBlock]$Script) {
    try {
        &$Script
    }
    finally {
        if ($Resource -is [IDisposable]) { $Resource.Dispose() }
    }
}

Using ($File = [IO.File]::CreateText("$PWD\blah.txt")) {
   $File.WriteLine(...)
}

Как это круто!

19 голосов
/ 21 мая 2009

Команда $$. Мне часто приходится повторять операции с одним и тем же путем к файлу. Например, проверьте файл, а затем откройте его в VIM. Функция $$ делает это тривиальным

PS> tf edit some\really\long\file\path.cpp
PS> gvim $$

Это коротко и просто, но это экономит много времени.

15 голосов
/ 22 мая 2009

Функция, которую я часто упускаю из виду, - это возможность передачи файла в оператор switch.

Switch будет выполнять итерацию по строкам и сопоставлять строки (или регулярные выражения с параметром -regex), содержимое переменных, чисел или строки можно передать в выражение, которое будет оцениваться как $ true или $ false

switch -file 'C:\test.txt' 
{   
  'sometext' {Do-Something}   
  $pwd {Do-SomethingElse}  
  42 {Write-Host "That's the answer."}  
  {Test-Path $_} {Do-AThirdThing}  
  default {'Nothing else matched'} 
}
13 голосов
/ 21 мая 2009

$ OFS - разделитель выходного поля . Удобный способ указать, как элементы массива разделяются при визуализации в строку:

PS> $OFS = ', '
PS> "$(1..5)"
1, 2, 3, 4, 5
PS> $OFS = ';'
PS> "$(1..5)"
1;2;3;4;5
PS> $OFS = $null # set back to default
PS> "$(1..5)"
1 2 3 4 5

Всегда гарантируем, что вы получите результат массива . Рассмотрим этот код:

PS> $files = dir *.iMayNotExist
PS> $files.length

$ файлы в этом случае могут быть $ null, скалярным значением или массивом значений. $ files.length не даст вам количество файлов, найденных для $ null или для одного файла. В случае одного файла вы получите размер файла !! Всякий раз, когда я не уверен, какой объем данных я получу, я всегда заключаю команду в подвыражение массива следующим образом:

PS> $files = @(dir *.iMayNotExist)
PS> $files.length # always returns number of files in array

Тогда $ files всегда будет массивом. Он может быть пустым или содержать только один элемент, но будет массивом. Это значительно упрощает рассуждения с результатом.

Поддержка ковариации массива:

PS> $arr = '127.0.0.1','192.168.1.100','192.168.1.101'
PS> $ips = [system.net.ipaddress[]]$arr
PS> $ips | ft IPAddressToString, AddressFamily -auto

IPAddressToString AddressFamily
----------------- -------------
127.0.0.1          InterNetwork
192.168.1.100      InterNetwork
192.168.1.101      InterNetwork

Сравнение массивов с помощью Compare-Object :

PS> $preamble = [System.Text.Encoding]::UTF8.GetPreamble()
PS> $preamble | foreach {"0x{0:X2}" -f $_}
0xEF
0xBB
0xBF
PS> $fileHeader = Get-Content Utf8File.txt -Enc byte -Total 3
PS> $fileheader | foreach {"0x{0:X2}" -f $_}
0xEF
0xBB
0xBF
PS> @(Compare-Object $preamble $fileHeader -sync 0).Length -eq 0
True

Если хотите узнать больше, посмотрите мою бесплатную электронную книгу - Effective PowerShell .

10 голосов
/ 22 мая 2009

Вдоль строк многопараметрических присваиваний.

$ list = 1,2,3,4

Пока ($ list) {
$ head, $ list = $ list
$ Голова
}

1
2
3
4

8 голосов
/ 26 мая 2009

Я использую это:

if (!$?) {  # if previous command was not successful
    Do some stuff
}

и я также немного использую $ _ (текущий объект конвейера), но они могут быть более известны, чем другие.

6 голосов
/ 24 мая 2009

Тот факт, что многие операторы также работают с массивами и возвращают элементы, для которых выполняется сравнение, или работают с каждым элементом массива независимо:

1..1000 -lt 800 -gt 400 -like "?[5-9]0" -replace 0 -as "int[]" -as "char[]" -notmatch "\d"

Это быстрее, чем Where-Object.

3 голосов
/ 15 октября 2011

Tab-поиск по вашей истории с #

Пример:

PS> Get-Process explorer
PS> "Форд Эксплорер"
PS> "Магеллан" | Add-Content "great explorers.txt"
PS> типа "great explorers.txt"
PS> #expl <- нажмите клавишу <tab>, чтобы пролистать записи истории, имеющие термин «expl»

3 голосов
/ 05 марта 2010

Не языковая функция, но очень полезная

f8 - берет уже введенный текст и ищет команду, начинающуюся с этого текста.

1 голос
/ 27 апреля 2012

Выполните итерацию в обратном порядке по последовательности, просто используйте len последовательности с 1 на другой стороне диапазона.

foreach (x в seq.length..1) {Do-Something seq [x]}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...