Поиск в PowerShell в строке и извлечение конкретных значений строки - PullRequest
0 голосов
/ 27 января 2019

У меня большой файл, который содержит много строк.Например:

ts=2019-01-16 network=1.1.1.1 system=irgendwas pid=100 bugReq=dasf something=else maybe=this

Из каждой строки я хочу извлечь следующую информацию:

ts=,system= & something=, но значения после = всегда меняются.

Iпопробовал это, но не смог заставить его работать:

$found = $string -match '.*system="(\d+)".*' if ($found) { $system= $matches[1]}

Ответы [ 3 ]

0 голосов
/ 28 января 2019

То, как работает журнал, который вы мне показываете, выглядит так, как будто есть 3 раздела, которые мы можем вырезать и вставить из Object, которые могут быть возвращены из новой строки Keypair, которые могут быть возвращены из пустого пространства Key, которые могут быть возвращены после удаления=

Я написал функцию для этого случая, используя эту идею

function ConvertTo-PsObjectArrayList($Text,$TextObjectSeparator,$KeyPairSeparator,$KeySeparator){
    $ArrayList = New-Object System.Collections.ArrayList
    $TestData -split $TextObjectSeparator | %{
        $PsObject = new-object System.Management.Automation.PSObject
        $_ -split $KeyPairSeparator | %{      
            $KeyPair = $_ -split $KeySeparator
            $PsObject | Add-Member -MemberType NoteProperty -Name $KeyPair[0] -Value $KeyPair[1]
        }
        $ArrayList.Add($PsObject) | out-null
    }
    return $ArrayList
}

$TestData = @'
ts=2019-01-16 network=1.1.1.1 system=irgendwas pid=100 bugReq=dasf something=else maybe=this
ts=2019-01-16 network=1.1.2.1 system=irgendwas pid=130 bugReq=dasf something=else
ts=2019-01-16 network=1.1.1.1 system=irgendwas pid=150 bugReq=dasf something=else maybe=this
ts=2019-01-16 network=1.1.1.1 system=irgendwas pid=110 bugReq=dasf something=else
'@

ConvertTo-PsObjectArrayList -Text $TestData -TextObjectSeparator "`r`n" -KeyPairSeparator " " -KeySeparator "=" | select TS, System, Something

Это вернет

ts         system    something
--         ------    ---------
2019-01-16 irgendwas else     
2019-01-16 irgendwas else     
2019-01-16 irgendwas else     
2019-01-16 irgendwas else
0 голосов
/ 28 января 2019

вот еще одно решение.[ grin ] он использует командлет ConvertFrom-StringData для разбора ввода в объекты.затем он создает [PSCustomObject] только с требуемыми реквизитами.наконец, он отправляет каждый объект в коллекцию $ Results.

, хотя при построении конечного пользовательского объекта следующая информация в данном случае не важна, важно знать, что вывод командлета ConvertFrom-StringData является стандартной хеш-таблицей.это означает, что порядок объектов почти наверняка НЕ ​​будет в исходном порядке. НЕ ожидайте, что все будет в порядке, в котором они появляются в источнике .

[edit = добавил новую строку данных со встроенными пробелами и обновленный шаблон -replace для обработки этого.]

# fake reading in a text file
#    in real life, use Get-Content
$InStuff = @(
    'ts=2019-01-16 network=1.1.1.1 system=irgendwas pid=100 bugReq=dasf something=else maybe=this'
    'ts=2019-01-16 network=1.1.1.2 system=PC-001 pid=100 bugReq=dasf something=OtherElse maybe=this'
    'ts=2019-01-16 network=1.1.1.66 system=PC-666 pid=100 bugReq=dasf something=ThisELse maybe=this'
    'ts=2019-01-16 network=1.1.1.3 system=PC-123 pid=100 bugReq=dasf something=AnotherElse maybe=this'
    'ts=2019-01-16 network=1.1.1.4 system=PC-004 Oo-LaLa another value with WhiteSpace id=100 bugReq=dasf something=Else-ish with Whitespace'
    )

$Results = foreach ($IS_Item in $InStuff)
    {
    # this requires that spaces ONLY be found as delimiters
    #    if you have embedded spaces, some sort of data format adjustment will be required
    #    now there is a need for handline embedded whitespace
    #$IS_Item -replace ' ', [environment]::NewLine |
    $IS_Item -replace '(\w{1,}=)', ('{0}{1}' -f [environment]::NewLine, '$1') |
        ConvertFrom-StringData |
        ForEach-Object {
            [PSCustomObject]@{
                TS = $_.ts
                System = $_.system
                Something = $_.something
                }
            }
    }

$Results

вывод на экран ...

TS         System                                       Something               
--         ------                                       ---------               
2019-01-16 irgendwas                                    else                    
2019-01-16 PC-001                                       OtherElse               
2019-01-16 PC-666                                       ThisELse                
2019-01-16 PC-123                                       AnotherElse             
2019-01-16 PC-004 Oo-LaLa another value with WhiteSpace Else-ish with Whitespace

это правильная коллекция простых объектов, поэтому она будет Export-CSV довольно аккуратно.[ ухмылка ]

0 голосов
/ 28 января 2019

Предполагая, что список пар «ключ-значение» каждой строки содержит только значения без внедренного пробела или кавычек :

# Sample input line.
$line = 'ts=2019-01-16 network=1.1.1.1 system=irgendwas pid1=100 bugReq=dasf something=else maybe=this'

# Parse the line into key-value pairs and create a variable for each.
$i = 0
foreach ($keyOrValue in $line -split '[= ]') {
  if ($i++ % 2 -eq 0) { $varName = $keyOrValue }
  else                { Set-Variable $varName $keyOrValue }
}

# $ts now contains '2019-01-16', $network '1.1.1.1', $system 'irgendwas', ...

Обратите внимание, как я немного изменил строку ввода образца для измененияpid до pid1, поскольку PowerShell не позволит вам создать переменную $PID, поскольку она является автоматической переменной, отражающей PID (идентификатор процесса) текущего сеанса.

Другой вариант (который также позволил бы избежать конфликта имен переменных) - создать хеш-таблицу для каждой строки ввода:

# Sample input line.
$line = 'ts=2019-01-16 network=1.1.1.1 system=irgendwas pid=100 bugReq=dasf something=else maybe=this'

# Parse the line into key-value pairs and create a variable for each.
$htValues = @{} # Initialize the hashtable.
$i = 0
foreach ($keyOrValue in $line -split '[= ]') {
  if ($i++ % 2 -eq 0) { $varName = $keyOrValue }
  else                { $htValues[$varName] = $keyOrValue }
}

# $htValues now has keys 'ts', 'network', 'system' with corresponding
# values, so you can access $htValues.ts to get '2019-01-16', for instance.

Этот подход имеет дополнительное преимущество:1018 * сбор хеш-таблиц, созданных для отдельных строк в общем массиве (например, $hashTableArray = foreach ($line in ...) { ... } - хотя с очень большим файлом, который может быть недоступен.

Заимствованиеидея из ответа Lee_Dailey , вы можете альтернативно использовать командлет ConvertFrom-StringData для создания хеш-таблицы, предварительно поместив каждую пару ключ-значение на свою собственную строку с помощью -replace оператор:

$htValues = ConvertFrom-StringData ($line -replace ' ', "`n")

Предупреждение re ConvertFrom-StringData заключается в том, что он интерпретирует \ символов.как начало escape-последовательности ;например, значение, такое как b\c breaks команда:

Convertfrom-StringData 'a=b\c' # ERROR: "parsing 'b\c' - Missing control character."

С положительной стороны, использование ConvertFrom-StringData на намного быстрее , чем ручноепарсинг с foreach.


В качестве отступления: командлет PowerShell Get-Content для чтения строк по одной (по умолчанию) удобен, но медленно .

Чтобы быстрее обработать строки (большого) текстового файла, используйте:

$file = 'file.txt'
foreach ($line in [System.IO.File]::ReadLines((Convert-Path $file))) {
  # ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...