如何使用Powershell转换文件内容

问题描述 投票:1回答:4

我有一个格式很奇怪的日志文件,我想将其转换为表。格式是每行包含多个键值对(每行相同)。我想转换这些行,以便每个属性成为包含该行值的表中的一列。

请注意,原始日志文件每行包含39个属性,日志文件约为80MB。

示例行:

date=2019-12-02 srcip=8.8.8.8 destip=8.8.4.4 srcintf="port2"
date=2019-12-01 srcip=8.8.8.8 destip=8.8.4.4 srcintf="xyz abc"
date=2019-12-03 srcip=8.8.8.8 destip=8.8.4.4 srcintf="port2"
date=2019-12-05 srcip=8.8.8.8 destip=8.8.4.4 srcintf="port2"
date=2019-12-07 srcip=8.8.8.8 destip=8.8.4.4 srcintf="port2"

我尝试过:

Get-Content .\testfile.log | select -First 10 | ConvertFrom-String | select p1, p2, p3 | ft | Format-Wide

但是这不会将属性名称分解为列名称。因此,在此示例中,我希望P1是日期,p2 srcip和p3 destip,并且希望删除每个值的第一部分。

Po

任何人都有任何技巧或创意,如何将其转换为表格?

powershell logfile
4个回答
3
投票

ConvertFrom-String提供基于分隔符的解析以及基于包含示例值的模板的基于启发式的解析。基于分隔符的解析会应用您无法控制的自动类型转换,并且模板语言的文档很少,其确切行为难以预测-最好完全避免使用此cmdlet。另请注意,它在PowerShell Core中不可用。

相反,我建议基于ConvertFrom-Stringswitch statement的方法来创建代表日志行的自定义对象(switch)的集合:

-split operator

注意:

  • 以上假定您的值具有无嵌入空格;如果这样做,则需要做更多工作-请参阅下一部分。

  • 要在variable中捕获生成的自定义对象,只需使用-split

    • [具有两条或多条日志行,[pscustomobject]成为# Use $objects = switch ...` to capture the generated objects in a variable. switch -File .\testfile.log { # Loop over all file lines default { $oht = [ordered] @{ } # Define an aux. ordered hashtable foreach ($keyValue in -split $_) { # Loop over key-value pairs $key, $value = $keyValue -split '=', 2 # Split pair into key and value $oht[$key] = $value -replace '^"|"$' # Add to hashtable with "..." removed } [pscustomobject] $oht # Convert to custom object and output. } } 实例的$objects = switch ...数组。如果即使在日志行仅是[[one的情况下也要确保$objects也成为数组,请使用[object[]][pscustomobject]实际上与$objects相同)。
  • 要将输出对象通过

    pipeline

  • 直接发送到其他cmdlet,请将[array] $objects = switch ...语句括在[array]中>
使用示例输入,将产生:

[object[]]


[switch]内部的支持具有嵌入式空格的值

的变量(例如& { ... }):此外,周围的date srcip destip srcintf ---- ----- ------ ------- 2019-12-02 8.8.8.8 8.8.4.4 port2 2019-12-01 8.8.8.8 8.8.4.4 port2 2019-12-03 8.8.8.8 8.8.4.4 port2 2019-12-05 8.8.8.8 8.8.4.4 port2 2019-12-07 8.8.8.8 8.8.4.4 port2 被删除。

"..."

请注意,不支持

嵌入式转义

srcintf="port 2"实例(例如"..."将不起作用。
说明:

  • [switch -file .\testfile.log { default { $oht = [ordered] @{ } foreach ($keyValue in $_ -split '(\w+=(?:[^"][^ ]*|"[^"]*"))' -notmatch '^\s*$') { $key, $value = $keyValue -split '=', 2 $oht[$key] = $value -replace '^"|"$' } [pscustomobject] $oht } } 被与"srcintf="port \"2\""标记匹配的$_ -split '(\w+=(?:[^"][^ ]*|"[^"]*"))'分割,并通过将表达式包含在regex中(创建捕获组),

    includes

    这些“分隔符key=valueWithoutSpaces输出的令牌中(默认情况下不包含分隔符)。
  • [key="value that may have spaces"然后从结果中清除空的和全空格的标记(“数据标记”,在我们的情况下不重要),实际上仅留下键值对。
  • [(...)将给定的键值令牌再见-split分成两个令牌,并使用解构分配将键和值分配给单独的变量。]​​>
  • -notmatch '^\s*$'将一个条目添加到辅助。带有键和值的哈希表,其中$key, $value = $keyValue -split '=', 2使用=从值的开头和结尾(如果存在)中删除$oht[$key] = $value -replace '^"|"$'
  • 所以您

    可能

    要做的是将每一行剪切成键值对的哈希表,而不是将它们传递给-replace '^"|"$'。这种方法有两个警告。为简单起见,您的源数据是用空格分隔的。如果您的实际数据包含空格(可以缓解),则会中断。另一个明显的警告是您无法保证属性顺序。
    -replace operator
    输出:

    -replace

    确定,出于讨论的目的,我将假设以下内容:

      数据在PSDATA.TXT文件中
  • 除了分隔名称/值对的空格之外,数据中没有其他空格。
  • 结果表格数据将所有值都视为字符串是可接受的。
  • 考虑到...
  • "

    ...将生成一个表,其中文件中的每一行都变为PSObject,其中字段以每个名称/值对中的名称作为名称,而字段的相关值则作为字符串。如果您不使用PowerShell v4或更高版本(我不确定3),则可以省略ConvertFrom-StringData,而PSObject中字段顺序的副作用不一定与文件。

    [如果您想拥有这些PSObject的数组以进行进一步处理,则可以将上面的整行包装在变量分配中,例如Get-Content c:\temp\so.txt | ForEach-Object{ [PSCustomObject](($_ -split " ") -join "`r`n" | ConvertFrom-StringData) } | Select-Object date, srcip, destip, srcintf ,如果您想将其发送到CSV文件,则只需添加date srcip destip srcintf ---- ----- ------ ------- 2019-12-02 8.8.8.8 8.8.4.4 "port2" 2019-12-01 8.8.8.8 8.8.4.4 "port2" 2019-12-03 8.8.8.8 8.8.4.4 "port2" 2019-12-05 8.8.8.8 8.8.4.4 "port2" 2019-12-07 8.8.8.8 8.8.4.4 "port2" 到结尾。

    我希望有一个数据表,因此您可以轻松地对日志文件进行排序,过滤,合并等。

    Get-Content -Path PSDATA.TXT | ForEach-Object {$_ -replace ' ','";' -replace '=','="' -replace '""','"'} | ForEach-Object {New-Object PSObject -Property (Invoke-Expression ("[Ordered]@{{{0}}}" -f $_))}


    1
    投票
    所以您

    可能


    1
    投票
    确定,出于讨论的目的,我将假设以下内容:

    0
    投票
    我希望有一个数据表,因此您可以轻松地对日志文件进行排序,过滤,合并等。
    © www.soinside.com 2019 - 2024. All rights reserved.