使用Powershell从日志文件中拆分字段

使用Powershell从日志文件中拆分字段,powershell,Powershell,Powershell相对较新,因此对于任何熟悉Powershell的人来说,这可能是一个非常简单的问题 我有一些日志文件(用于AWS S3 bucket),其中包含一组由空格分隔的文本字段(耶…)。日志每隔20秒左右在单独的文件中创建一次,因此一个月的日志价值超过100000个文件 我需要一次性下载它们,并将它们合并到一个文件中,这样我就可以将其复制到亚马逊红移数据库中。这部分很好。我正在使用AWS命令行工具将本地文件夹与S3 bucket同步,并使用include和exclude过滤器获取我想

Powershell相对较新,因此对于任何熟悉Powershell的人来说,这可能是一个非常简单的问题

我有一些日志文件(用于AWS S3 bucket),其中包含一组由空格分隔的文本字段(耶…)。日志每隔20秒左右在单独的文件中创建一次,因此一个月的日志价值超过100000个文件

我需要一次性下载它们,并将它们合并到一个文件中,这样我就可以将其复制到亚马逊红移数据库中。这部分很好。我正在使用AWS命令行工具将本地文件夹与S3 bucket同步,并使用include和exclude过滤器获取我想要的日志,然后执行以下操作,仅将包含“OBJECT”的条目写入组合文件:

Get-ChildItem -recurse -include "*" | % { Get-Content $_ -ReadCount 0 | Select-String "OBJECT" | Add-Content logfiles\printlogs2017-09.txt }
然而,结果文件的大小超过700MB,尽管这仍然有效,而且我可以在红移时提取我想要的内容,事实上,我只需要其中的三个字段,所以我最好只将这三个字段写入合并文件

我想,如果行是用空格分隔的,这实际上就像将一个句子拆分成单词,然后只从中选取一些单词,因此尝试通过每次将一行放入一个变量中,然后使用foreach和split()将该行拆分为一个字段数组,然后只输出我想要的字段,但是我尝试的每一种组合要么是错误的,因为我得到了管道的参数或结构(这里应该注意,我还不了解管道),要么是因为数组是空的,所以它没有输出任何东西

如何编辑上面的代码行,使其包含一个部分,该部分在空间上分割源代码的每一行,然后只将结果数组的某些项(我认为是7、8和10)写入新文件,并用逗号分隔。最终,我追求的是(我知道这是错误的):


最后我想要的是:field7,field8,field10这里有两个可能的选项供您选择,它们都会生成一个CSV(这是我假设您想要的)

选项1:从拆分创建自定义对象,然后输出该对象并将其导入到
导出CSV

Get-ChildItem -recurse -include "2017-09-01-00*" | ForEach-Object { 
    Get-Content $_ | ForEach-Object { 
        $fields = $_.split(' ')
        [pscustomobject]@{
            Field7 = $fields[7]
            Field8 = $fields[8]
            Field10 = $fields[10]
        }
    }
} | Export-CSV logfiles\printlogs2017-09-test.csv -NoTypeInformation
Get-ChildItem -recurse -include "2017-09-01-00*" | ForEach-Object { 
    Import-CSV $_ -Delimiter ' ' -Header 'Field0','Field1','Field2','Field3','Field4','Field5','Field6','Field7','Field8','Field9','Field10' | Select Field7,Field8,Field10
} | Export-CSV logfiles\printlogs2017-09-test.csv -NoTypeInformation

选项2:使用定义了标题行的
导入CSV
(如果您的日志文件已经有标题行,这是可选的),并使用指定为空格的分隔符,使用
选择对象
进行筛选以获取所需字段,然后通过
导出CSV
进行导出:

Get-ChildItem -recurse -include "2017-09-01-00*" | ForEach-Object { 
    Get-Content $_ | ForEach-Object { 
        $fields = $_.split(' ')
        [pscustomobject]@{
            Field7 = $fields[7]
            Field8 = $fields[8]
            Field10 = $fields[10]
        }
    }
} | Export-CSV logfiles\printlogs2017-09-test.csv -NoTypeInformation
Get-ChildItem -recurse -include "2017-09-01-00*" | ForEach-Object { 
    Import-CSV $_ -Delimiter ' ' -Header 'Field0','Field1','Field2','Field3','Field4','Field5','Field6','Field7','Field8','Field9','Field10' | Select Field7,Field8,Field10
} | Export-CSV logfiles\printlogs2017-09-test.csv -NoTypeInformation
显然,您可以自定义这两种格式中的字段名,以适合您的数据


我建议使用第二种方法,因为依赖存在的数组项总是有点危险。

是否可以包含日志样本?这样可能更容易理解这个问题。不是确切的样本,不是。它们包含了太多的敏感信息。但事实上,内容并不重要。这是一堆字符串,带有空格。把它们想象成句子。对于一行,它们看起来都是这样的:
e211a6bb2bbbcfa29822a400c4c05ba18cae3e7332286292db4e477e83b7b10e某种url[dd/MM/yyyy:hh:MM:ss+0000]1.23.1.49 arn:aws:iam::123456789:user/user id 83A823B93D923R REST.PUT.OBJECT 20170901/folder/subfolder/documentname.pdf PUT/20170901/folder/subfolder/documentname.pdf 200--348247 119 48-aws sdk java/1.4.4.1-linux/some.long/software/version id
这些看起来很有用。盲目依赖存在的数组项和盲目依赖源文件中存在的字段之间有什么区别?与导入CSV命令上的设置-Delimiter相比,split()是否有一些不一致的行为?哦,还有,第二个选项是否也会每次写入标题,或者只是在导入阶段使用它们?我不想在整个合并输出中写入100000个标题行;)主要的区别是,如果你依赖数组项而它不存在,你会得到一个大的红色错误消息,如果你依赖字段存在而它不存在,你只会在CSV中得到一个空条目而没有错误(我认为)。它将使用它们作为输入和输出,但是它应该只写一次,因为
导出CSV
在外部循环的末尾(注意,我最初没有这样做)。太好了,谢谢Mark。我已经用一组定义好的字段名实现了第二个选项,它似乎可以处理一小部分文件。我现在要把它全套地检查一遍,看看会发生什么。