Работа с текстовым выводом

Несмотря на огромное количество новых возможностей PowerShell'а, обьектный подход, и т.д., он всё равно прекрасно работает со старыми утилитами командной строки. Можно прекрасно использовать его вместо cmd.exe.

Но иногда хочется не просто воспользоваться классическими утилитами, а сделать это используя новые возможности PoSH'а.

Есть у меня одна очень хорошая утилитка whosip.exe, делающая запрос whois по имени или ипу хоста и возвращающая результат в виде текстовых строк, где имя параметра отделено от его значения двоеточием:

PS L:\PowerShell> whosip.exe ya.ru

WHOIS Source: RIPE NCC
IP Address:   213.180.204.8
Country:      Russian Federation
Network Name: YANDEX-204-0
Owner Name:   Yandex corporate network
From IP:      213.180.204.0
To IP:        213.180.204.31
Allocated:    Yes
Contact Name: Yandex LLC Network Operations
Address:      Yandex LLC, 40A Vavilova st., 117333, Moscow, Russia
Email:        noc@yandex.net
Abuse Email:  abuse@yandex.ru
Phone:        +7 495 9743555
Fax:          +7 495 9743565

Очень похоже на вывод Format-List?😉 Похоже, но не то. Была бы это PoSH'евская утилитка то можно было бы легко сделать много полезных вещей. Например посмотреть страны ip адресов взятых из списка:

PS L:\PowerShell> Get-Content iplist.txt | ForEach {
>>  Get-Whois $_ } | Format-Table ipaddress, country, email -AutoSize
>>

IPAddress     Country            Email
---------     -------            -----
72.14.207.99  USA - California   arin-contact@google.com
213.180.204.8 Russian Federation noc@yandex.net
81.19.66.46   Russian Federation denis@rambler-co.ru

Вот только это текстовая утилита, и чтоб получить такой результат придётся порядочно повозиться. Или нет?

Сейчас мы попробуем создать функцию-обёртку для этой команды.
Для начала создадим «пустой объект», который будем выдавать в качестве результата, потом мы наделим его нужными свойствами:

$result = New-Object PSObject

Вывод всех обычных текстовых консольных команд PowerShell превращает в массив строк, и в таком виде выводит (Визуально результат не отличается от привычного, но добавляет массу преимуществ :)). Так что мы можем отфильтровать строки с помощью Where-Object:

whosip ya.ru | Where { $_ -match "(.+?): *(.+)"}

Тут я применил регулярное выражение, которое во первых отбирает лишь строки нужного нам формата (параметр, двоеточие, значение), и во вторых помещает название параметра и значение в специальный массив $matches, с индексами 1 и 2 соответственно. Для наглядности возьмем одну строчку:

PS L:\PowerShell> "IP Address:   213.180.204.8" -match "(.+?): *(.+)"
True

Выражение истинно. В массив $matches были помещены соответствующие значения:

PS L:\PowerShell> $matches

Name                           Value
----                           -----
2                              213.180.204.8
1                              IP Address
0                              IP Address:   213.180.204.8

Под индексом 0 находится вся совпавшая строка. (Регулярные выражения (RegExp) могут показатся очень сложными для понимания, но они стоят того. Независимо от языка где они используются они позволяют секономить кучу времени при операциях со строками)

Продолжим… У нас теперь есть имя параметра и его значение, осталось прикрутить их к $result🙂

$result | Add-Member -MemberType noteProperty -Name ($matches[1] -replace " ") -Value $matches[2]

Эта хитрая команда прицепит к $result свойство с именем из $matches[1], и значением из $matches[2]. Оператор -replace тут нужен для того чтобы убрать из названий параметров все пробелы, работать будет и с ними, но тогда параметры с пробелами придётся всегда заключать в кавычки, а это неудобно.

Ну и собственно всё. Осталось записать итоговую функцию, и закинуть её в профиль🙂

function Get-Whois ($ip)
{
$result = New-Object PSObject
whosip $ip | where { $_ -match "(.+?): *(.+)" } |
foreach { $result | Add-Member noteProperty ($matches[1] -replace " ") $matches[2]}
$result
}

Как обычно, можно просто скопировать отсюда в консоль.

Всё, функция из начала поста работает🙂 И не только она…😉
Любимый Get-Member😉

PS L:\PowerShell> Get-Whois ya.ru | Get-Member


   TypeName: System.Management.Automation.PSCustomObject

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       System.Boolean Equals(Object obj)
GetHashCode Method       System.Int32 GetHashCode()
GetType     Method       System.Type GetType()
ToString    Method       System.String ToString()
AbuseEmail  NoteProperty System.String AbuseEmail=abuse@yandex.ru
Address     NoteProperty System.String Address=Yandex LLC, 40A Vavilova st., 117333, Moscow, Russia
Allocated   NoteProperty System.String Allocated=Yes
ContactName NoteProperty System.String ContactName=Yandex LLC Network Operations
...

Format-List…

PS L:\PowerShell> Get-Whois ya.ru | Format-List

WHOISSource : RIPE NCC
IPAddress   : 213.180.204.8
Country     : Russian Federation
NetworkName : YANDEX-204-0
...

Похоже на оригинал?😉

Да, кстати, можно засунуть результат в переменную:

$ya = Get-Whois ya.ru

И набрав например $ya.a[tab] наслаждаться автодополнением свойств🙂

Опубликовано в PowerShell. 5 комментариев »

комментариев 5 to “Работа с текстовым выводом”

  1. Roman Says:

    А как быть с такими адресами:
    [roman] whosip.exe 192.168.2.1
    Bad host name or IP address
    [roman] whosip.exe 192.168.2.1
    Bad host name or IP address
    [roman] whosip.exe 192.168.2.0
    Bad host name or IP address
    [roman] whosip.exe 172.20.1.11
    Bad host name or IP address
    [roman]

    Функции выдают следующее:
    [roman] Get-Whois 192.168.2.1

    [roman] Get-Whois 192.168.2.0

    [roman] Get-Whois 172.20.1.11

    [roman]

    Где обработчик ошибок?

  2. Xaegr Says:

    2 Roman:
    >Где обработчик ошибок?
    А надо?🙂 Нате😉

    function Get-Whois ($ip)
    {
    $result = New-Object PSObject
    $raw = whosip $ip
    if ($raw -like «Bad*»){throw $raw}
    $raw | where { $_ -match «(.+?): *(.+)» } |
    foreach { $result | Add-Member noteProperty ($matches[1] -replace » «) $matches[2]}
    $result
    }

  3. Roman Says:

    Спасибо огромное!

  4. Roman Says:

    а как быть с таким вариантом. Ошибка передается конвееру😦

    [roman] Get-Whois 172.20.1.11 | Format-List networkname,ownername,fromip,toip
    Bad host name or IP address
    В C:\Document\WindowsPowerShell\Microsoft.PowerShell_profile.ps1:18 знак:29
    + if ($raw -like «Bad*»){throw <<<< $raw}

    [roman] Get-Whois 212.44.64.6 | Format-List networkname,ownername,fromip,toip

    NetworkName : GAZINTER-NET
    OwnerName : OOO «GazInterNet»
    FromIP : 212.44.64.0
    ToIP : 212.44.91.255

  5. Xaegr Says:

    Ммм. До конвейера ничего не доходит, выполнение прерывается на ошибке:
    [PS C:\] Get-Whois 172.20.1.11 | %{«test»}
    Bad host name or IP address
    At line:5 char:29
    + if ($raw -like “Bad*”){throw <<<< $raw}


Обсуждение закрыто.

%d такие блоггеры, как: