none
PS: Порядок обработки, Split и управление выводом. RRS feed

  • Вопрос

  • Добрые сутки, уважаемые.

    Запутался в синтаксисе и порядке вывода. Есть текстовый файл вида:

    \\RCB-004 2600 Service Pack 3 C:\WINDOWS   Microsoft Windows XP 
    \\RCB-007 2600 Service Pack 3 C:\WINDOWS   Microsoft Windows XP
    \\RCB-008 2600 Service Pack 3 C:\WINDOWS   Microsoft Windows XP
    \\RCB-011 2600 Service Pack 2 C:\WINDOWS   Microsoft Windows XP
    \\RCB-016 2195 Service Pack 4 C:\WINNT  Microsoft Windows 2000 
    \\RCB-017 2600 Service Pack 3 C:\WINDOWS   Microsoft Windows XP 
    \\RCB-018 2600 Service Pack 3 C:\WINDOWS   Microsoft Windows XP 
    \\RCB-021 2195 Service Pack 4 C:\WINNT  Microsoft Windows 2000 

    Желаю из него выделить подстроки, грубо говоря \\RCB-???. При чём не все, а лишь для Windows 2000. На самом деле разделитель табуляция.
    ...И втыкаюсь почти моментально в собственное непонимание конвеерной обработки и прочих важных вещей.
    PS> type config.txt | where {$_ -match "WINDOWS 2000"; $_.Split("`t")} | out-file h:\fff.txt
    Помогите пожалуйста разобраться. Мне бы хотелось присвоить к примеру результаты сплита другой переменной и затем передать выводу нулевой элемент образовавшегося массива. Но не могу - следующему пайпу в таком случае достанется последнее значение такой переменной. Хотел бы вынести сплит из where, но PS ругается на "Выражения допускаются только в качестве первого элемента конвейера.". Как бы мне всё это разрешить? И более того, как бы сделать обработку построчной, а не передавать дальше сокращающийся вывод?
    При попытке всё и вся организовать в where:
    PS > type config.txt | where {$_ -match "WINDOWS 2000"; write-host $_.Split("`t")[0] } | out-file h:\fff.txt
    Всё выходит как-то совсем не так, как хотелось бы. Файл полон искомыми строками, но полной длинны. А вот на экране отражаются те самые подстроки \\RCB-??? из строк, не удовлетворяющих условиям -match.

    ЗЫ: С For-овскими подстроками толи проще было, толи привык просто.
    26 ноября 2009 г. 13:50

Ответы

  • Может можно и короче:

    $file = get-content .\1.txt
    $file | ? { $_ -match ".*2000" } | % { $_ -split "`t" } | ? { $_ -match "\\RCB-.+" }
    • Помечено в качестве ответа anyaspid 27 ноября 2009 г. 8:18
    26 ноября 2009 г. 16:14
  • >Желаю из него выделить подстроки, грубо говоря \\RCB-???. При чём не все, а лишь для Windows 2000. На самом деле разделитель табуляция.

    Ну это вообще просто.
    import-csv file.txt -Header "Name","Version","ServicePack","WinDir","WinVer" -Delimiter "`t" |
    where {$_.WinVer -eq "Microsoft Windows 2000"} | select -expandProperty Name

    Если использовать ваш вариант:
    PS> type config.txt | where {$_ -match "WINDOWS 2000"}| foreach {$_.Split("`t")[0]} | out-file h:\fff.txt

    >ЗЫ: С For-овскими подстроками толи проще было, толи привык просто.
    Именно привычка :)

    >$file | ? { $_ -match ".*2000" } | % { $_ -split "`t" } | ? { $_ -match "\\RCB-.+" }
    в регулярном выражении .* совершенно излишне. Регекспы и так по умолчанию ищут лишь вхождение строки.

    Пользуясь случаем, рекомендую всем ознакомиться - http://xaegr.wordpress.com/2009/11/20/regexp-1-intro/ :)

    ЗЫ: А если делать с помощью регулярных выражений, я бы сделал так:
    gc .\file1.txt |where {$_ -match '^(?<Name>\S+)\t.+\t(?<Version>[^\t]+)$'}|where {$matches.Version -eq "Microsoft Windows 2000"} | foreach {$matches.name}
    Сложно, зато максимально четко :) Если без имён, то так:
    gc .\file1.txt |where {$_ -match '^(\S+)\t.+\t([^\t]+)$'}|where {$matches[1] -eq "Microsoft Windows 2000"} | foreach {$matches[2]}


    AKA Xaegr, MCSE: Security, Messaging; MCITP: Server\Enterprise Administrator; Блог: http://xaegr.wordpress.com
    • Помечено в качестве ответа anyaspid 27 ноября 2009 г. 7:19
    27 ноября 2009 г. 6:02
    Модератор

Все ответы

  • Может можно и короче:

    $file = get-content .\1.txt
    $file | ? { $_ -match ".*2000" } | % { $_ -split "`t" } | ? { $_ -match "\\RCB-.+" }
    • Помечено в качестве ответа anyaspid 27 ноября 2009 г. 8:18
    26 ноября 2009 г. 16:14
  • >Желаю из него выделить подстроки, грубо говоря \\RCB-???. При чём не все, а лишь для Windows 2000. На самом деле разделитель табуляция.

    Ну это вообще просто.
    import-csv file.txt -Header "Name","Version","ServicePack","WinDir","WinVer" -Delimiter "`t" |
    where {$_.WinVer -eq "Microsoft Windows 2000"} | select -expandProperty Name

    Если использовать ваш вариант:
    PS> type config.txt | where {$_ -match "WINDOWS 2000"}| foreach {$_.Split("`t")[0]} | out-file h:\fff.txt

    >ЗЫ: С For-овскими подстроками толи проще было, толи привык просто.
    Именно привычка :)

    >$file | ? { $_ -match ".*2000" } | % { $_ -split "`t" } | ? { $_ -match "\\RCB-.+" }
    в регулярном выражении .* совершенно излишне. Регекспы и так по умолчанию ищут лишь вхождение строки.

    Пользуясь случаем, рекомендую всем ознакомиться - http://xaegr.wordpress.com/2009/11/20/regexp-1-intro/ :)

    ЗЫ: А если делать с помощью регулярных выражений, я бы сделал так:
    gc .\file1.txt |where {$_ -match '^(?<Name>\S+)\t.+\t(?<Version>[^\t]+)$'}|where {$matches.Version -eq "Microsoft Windows 2000"} | foreach {$matches.name}
    Сложно, зато максимально четко :) Если без имён, то так:
    gc .\file1.txt |where {$_ -match '^(\S+)\t.+\t([^\t]+)$'}|where {$matches[1] -eq "Microsoft Windows 2000"} | foreach {$matches[2]}


    AKA Xaegr, MCSE: Security, Messaging; MCITP: Server\Enterprise Administrator; Блог: http://xaegr.wordpress.com
    • Помечено в качестве ответа anyaspid 27 ноября 2009 г. 7:19
    27 ноября 2009 г. 6:02
    Модератор