从多个文件中读取数字并求和

时间:2017-04-11 12:11:26

标签: powershell

我有一个日志文件C:\ temp \ data.log 它包含以下数据:

totalSize = 222,6GB

totalSize = 4,2GB

totalSize = 56,2GB

我的目标是从文件中提取数字并总结它们,包括逗号后面的数字。到目前为止,如果我没有正则表达逗号后的值包含的数字,它只能使用逗号前面的数字。我遇到的另一个问题是,如果文件只包含一行,如下例所示,如果它只包含一行,则将数字222拆分为三个文件,其中包含三个文件中的数字2。如果上面的日志文件包含2行或更多行,它可以正常工作并总结,只要我不使用逗号值。

totalSize                      = 222,6GB

以下是用于添加到逗号中包含的现有变量$regex末尾的正则表达式的一些代码:

[,](\d{1,})

我没有包含上述正则表达式,因为它没有正确总结。

整个脚本如下:

#Create path variable to store contents grabbed from $log_file
$extracted_strings = "C:\temp\amount.txt"
#Create path variable to read from original file
$log_file = "C:\temp\data.log"
#Read data from file $log_file
Get-Content -Path $log_file | Select-String "(totalSize = )" | out-file $extracted_strings
#Create path variable to write only numbers to file $output_numbers
$output_numbers = "C:\temp\amountresult.log"
#Create path variable to write to file jobblog1
$joblog1_file = "C:\temp\joblog1.txt"
#Create path variable to write to file jobblog2
$joblog2_file = "C:\temp\joblog2.txt"
#Create path variable to write to file jobblog3
$joblog3_file = "C:\temp\joblog3.txt"
#Create path variable to write to file jobblog4
$joblog4_file = "C:\temp\joblog4.txt"
#Create path variable to write to file jobblog5
$joblog5_file = "C:\temp\joblog5.txt"
#Create pattern variable to read with select string
$regex = "[= ](\d{1,})"
select-string -Path $extracted_strings -Pattern $regex -AllMatches | % { $_.Matches } | % { $_.Value }  > $output_numbers
(Get-Content -Path $output_numbers)[0..0] -replace '\s' > $joblog1_file
(Get-Content -Path $output_numbers)[1..1] -replace '\s' > $joblog2_file
(Get-Content -Path $output_numbers)[2..2] -replace '\s' > $joblog3_file
(Get-Content -Path $output_numbers)[3..3] -replace '\s' > $joblog4_file
(Get-Content -Path $output_numbers)[4..4] -replace '\s' > $joblog5_file
$jobdata0 = (Get-Content -Path $joblog1_file)
$jobdata1 = (Get-Content -Path $joblog2_file)
$jobdata2 = (Get-Content -Path $joblog3_file)
$jobdata3 = (Get-Content -Path $joblog4_file)
$jobdata4 = (Get-Content -Path $joblog5_file)
$result = $jobdata0  + $jobdata1 + $jobdata2 + $jobdata3 + $jobdata4
$result

所以我的问题是:

  1. 如果文件C:\ temp \ data.log只包含一个字符串而不将该单个数字分成多个文件,我该如何才能使其工作。如果它包含多个字符串,它也应该有效,因为它现在可以使用多个字符串。

  2. 如何在计算中包含逗号值?

  3. 如果我运行这个脚本,我得到的结果应该是282,也许甚至可以缩短脚本?

2 个答案:

答案 0 :(得分:3)

其中$log_file的内容与上例相同。

Get-Content $log_file | Where-Object{$_ -match "\d+(,\d+)?"} | 
    ForEach-Object{[double]($matches[0] -replace ",",".")} | 
    Measure-Object -Sum | 
    Select-Object -ExpandProperty sum

将具有数值的所有行与可选逗号匹配。我假设它们可以是可选的,因为我不知道整数是如何出现的。用句点替换逗号并转换为double。使用测量对象,我们总结所有值并扩展结果。

不是唯一的方法,但它很容易理解发生了什么。

您始终可以将上面的内容包装在一个循环中,以便您可以将其用于多个文件。 Get-ChildItem "C:temp\" -Filter "job*" | ForEach-Object ......等等。

答案 1 :(得分:1)

Matt's helpful answer显示了简洁有效的解决方案。

至于您尝试的内容

至于为什么带有单个令牌的行(例如222,6)可以在此命令中产生多个输出:

select-string -Path $extracted_strings -Pattern $regex -AllMatches | 
  % { $_.Matches } | % { $_.Value }  > $output_numbers

您的正则表达式[= ](\d{1,}) 解释症状,但只有\d{1,},因为这会捕获2226 < em>单独,由于-AllMatches

[= ](\d{1,})可能无法执行您想要的操作,因为[= ]匹配的单个字符可以 a {{ 1}} 一个空格;使用您的样本输入,这只会匹配数字前的空格 要按顺序匹配字符 ,只需将它们放在一起:=

另请注意,即使您将= (\d{1,})封装在\d{1,}中以创建捕获组,您的后续代码也不会实际使用该捕获组匹配的内容;仅当您需要优先级时才使用(...)(在这种情况下,您甚至可以选择退出使用(...)的子表达式捕获),或者如果您确实需要访问子表达式匹配的内容。

那就是说,你可以在这里实际使用一个捕获组(另一种方法是使用一个后置断言),它允许你匹配前导(?:...)的稳健性并仅提取感兴趣的数字标记(以后需要修剪空格) 如果我们将=<space>简化为\d{1,}并附加\d+以匹配逗号后面的数字,我们会得到:

,\d+

= (\d+,\d+) 返回的[System.Text.RegularExpressions.Match]实例允许我们通过Select-String属性访问捕获组捕获的内容(以下简化示例也适用于多个输入行):< / p>

.Groups

旁注:您的代码包含大量重复,可以通过数组和管道消除;例如:

> 'totalSize = 222,6GB' | Select-String '= (\d+,\d+)' | % { $_.Matches.Groups[1].Value }
222,6

可以替换为(使用管道创建数组文件名):

$joblog1_file = "C:\temp\joblog1.txt"
$joblog2_file = "C:\temp\joblog2.txt"
$joblog3_file = "C:\temp\joblog3.txt"
$joblog4_file = "C:\temp\joblog4.txt"
$joblog5_file = "C:\temp\joblog5.txt"

$joblog_files = 1..5 | % { "C:\temp\joblog$_.txt" }

然后可以替换为(将文件名的数组传递给$jobdata0 = (Get-Content -Path $joblog1_file) $jobdata1 = (Get-Content -Path $joblog2_file) $jobdata2 = (Get-Content -Path $joblog3_file) $jobdata3 = (Get-Content -Path $joblog4_file) $jobdata4 = (Get-Content -Path $joblog5_file) $result = $jobdata0 + $jobdata1 + $jobdata2 + $jobdata3 + $jobdata4 ):

Get-Content
相关问题