Ищем PowerShell эквивалент конкретной команды awk - PullRequest
3 голосов
/ 01 июля 2010

Мой гугл-фу снова меня подводит.Информация (вероятно) там, но я не могу ее найти.Я знаю UNIX как руку, использую Cygwin и т. Д. Однако, учитывая возросшую доступность Powershell на серверах и (по крайней мере, на производственных серверах) трудности с установкой Cygwin, я пытаюсь подобрать Powershell.Если не что иное, это еще одно оружие в моем арсенале.

По сути, я ищу Powershell, эквивалентный команде awk:

awk '$9 == "503" { print $0 }' < access_log

Для тех, кто не знает awk,это в основном сравнение поля 9 входного файла, а затем выполнение блока (это журнал доступа apache, поэтому он возвращает мне все строки из access_log, где возвращен код состояния HTTP 503).Awk автоматически обрабатывает разбиение файла на поля на основе пробелов;$ 0 - это целая строка (без изменений) с отдельными полями, входящими в $ 1, $ 2, ... [и т. Д.].

Я знаю, что могу использовать разбиение следующим образом:

cat access_log | %{ $_.split() }

, чторазбивает входящие строки в массив, но я не могу понять, как использовать select-object или where-object для выбора (и вывода) целых строк на основе заданного поля.

Альтернативаselect-string но, похоже, я не вижу способа передать выражение по линии %{ $_.split()[8] -eq "503" }.(Я отмечаю, что powershell основан на нуле, поэтому обращаю внимание на поле 8).

Я не уверен, что здесь упускаю что-то очевидное, и я не нашел подходящего google-fu, чтобы дать мнеинформация (поэтому не удивлюсь, если это где-то обман).

Приветствует любую помощь: -)

Ответы [ 3 ]

4 голосов
/ 01 июля 2010

Да, где-объект (псевдоним?) Лучше в этом случае:

cat access_log | ?{($_ -split '\s+',0,'regexmatch')[8] -eq 503} 

Обратите внимание, что метод разделения .NET создает пустые строковые записи для последовательных пробелов, поэтому я использую оператор -split в PowerShell 2.0, чтобы избежать этого.

Мое регулярное выражение слабо в этой области, но я думаю, что есть способ получить 9-е поле с помощью регулярного выражения (легче, чем подход с мертвым мозгом ниже - кто-нибудь ??):

Обновленный шаблон регулярных выражений для комментария Йоханнеса:

cat access_log | Select-String '^\s*(?:\w+\s+){8}503'
3 голосов
/ 01 июля 2010

Нашел ответ - хотя все равно рад видеть, есть ли альтернативные способы сделать это [поэтому я оставлю это без ответа на пару дней, чтобы посмотреть, есть ли у кого-то еще альтернативные методы] Метод, который я нашел:

cat access_log | where-object { $_.split()[8] -eq "503" }

который может быть сокращен до:

cat access_log | where { $_.split()[8] -eq 503 }

Так что это был случай, когда все было в порядке. Первоначально я шел по правильному пути, но мешал слишком много труб.

0 голосов
/ 01 июля 2010

Как я понимаю из кода, который вы разместили, вы ищете строки с 9-ю полями '503' и затем записываете 1-е поле этих строк? Если так:

Get-Content -Path "access_log" | ForEach-Object {
    if ($_ -match '(?<Field0>\d+)\s(?:\d+\s){7}503')
    {
        Write-Host $Matches["Field0"]
    }
}

EDIT:

Пример использования Select-String (лучше, чем мой предыдущий):

Select-String -Path "access_log" -Pattern '(?<Field0>\d+)\s(?:\d+\s){7}503' | ForEach-Object {
    Write-Host $_.Matches[0].Groups["Field0"]
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...