21. PowerShell -- 文本处理

  • PowerShell 文本处理

实例一:求所有电阻值的个数,平均值,总和,最大值,最小值。

问题描述:

有如下一段文本文件,开头有许多描述,字符“~”为有用数据的开始标志,要求:求所有电阻值的个数,平均值,总和,最大值,最小值。

 

这是一份格式较为规则的文本文件报表。

#文件头有一些无用的描述信息

~

深度         电阻值      放射性值

10            1.5            2.4

20            0.4            1.9

30            2.5            0.5

40            1.3

50            3.1


先不解释,直接贴脚本:

#加载文件,并过滤空行

$fullText=Get-Content .\a.txt | where { !([string]::IsNullOrWhiteSpace($_))}

#寻找文件头开始标志

$startFlagIndex=-1

For ($i = 1; $i -lt $fullText.Length; $i++)

   {

      if($fullText[$i].Contains("~"))

      {

        $startFlagIndex=$i

        break

      }

 

   }

#去掉文件头

$fullText=$fullText | Select-Object -Skip ($startFlagIndex+1) 

<#

 #将文件转换成CSV格式,然后再从CSV转换成对象

 #几经周折后,再要深入进行数据处理,将会变得非常方便

#>

$objs=$fullText | foreach{

    $tokens= $_.Split(‘ ‘,[StringSplitOptions]::RemoveEmptyEntries)

    ‘"{0}"‘ -f [string]::Join(‘","‘,$tokens)

} | ConvertFrom-Csv

 

#统计放射性值为空的对象

Write-Host "统计放射性值为空的对象"

$objs | where { $_.放射性值 -ne $null } | Format-Table -AutoSize

 

#求所有电阻值的个数,平均值,总和,最大值,最小值

Write-Host "求所有电阻值的个数,平均值,总和,最大值,最小值:"

$objs |  Measure-Object -Property 电阻值-Average -Sum -Maximum -Minimum

输出示例:

统计放射性值为空的对象

深度电阻值放射性值

-- --- ----

10 1.5 2.4

20 0.4 1.9

30 2.5 0.5

 

求所有电阻值的个数,平均值,总和,最大值,最小值:

Count    : 5

Average  : 1.76

Sum      : 8.8

Maximum  : 3.1

Minimum  : 0.4

Property : 电阻值

回过头再看,脚本完全可以优化为一个foreach循环,每行文本只遍历一次。之所以多次一举,是为了演示分析问题的过程。同样也能得出一个结论,如果可以尽最大可能从数据源拿到CSV文件格式的数据,PowerShell处理起来更方便,一行搞定!

 

实例二:要求打印出成绩相同的学生及成绩。

问题描述
给出一段学生成绩文本文件如下:

李一 93

王二 83

王三 93

李四 60

王五 75

马六 61

孙七 75

刘八 75

要求打印出成绩相同的学生及成绩。

李一 93

王三 93

王五 75

孙七 75

刘八 75

 

问题分析:
第一遍遍历,先须要一张哈希表保存各个成绩的出现的次数。
第二遍遍历,将成绩出现次数大于2的名单打印。

演示脚本:

$scoreTables=@{}

$stus=Get-Content .\ScoresFile.txt |

foreach {

$stu=$_ -split " "

if($scoreTables.ContainsKey($stu[1]))

{

 $scoreTables[$stu[1]]++

}

else {

    $scoreTables[$stu[1]]=1

}

@{ Score=$stu[1];Name=$stu[0] }

$stus | where {

$scoreTables[$_.Score] -gt 1

} | foreach {"{0} {1}" -f $_.Name,$_.Score }

 

group-object实现统计,比较完美,稍作整理,也贴在这里:

Get-Content .\a.txt | ForEach-Object {

[PSCustomObject]@{

 Name = $_.split()[0]

 Value = $_.split()[1]

 }

} | Group-Object Value | Where-Object { $_.Count -gt 1 }|

 ForEach-Object { $_.Group | ForEach-Object { "{0} {1}" -f $_.name,$_.value } }

 

 #为了和源文件格式保持一直,加入格式化

 

实例三:将原始文本转换成对象

 

原始文本

”data1″:111,”data2″:22,”data3″:3,”data4″:4444444,”data5″:589

要求:转换成对象

$rawTxt=‘"data1":111,"data2":22,"data3":3,"data4":4444444‘

$rawTxt -split ‘,‘ | ForEach-Object {

   $temp= $_ -split ‘:‘

   "{0}={1}" -f $temp[0].Substring(1,$temp[0].Length-2),$temp[1]

} | ConvertFrom-StringData

 

实例四:提取CSV文件中的域名

有一个CSV文件,其中包含了成千上万的URL链接,每个链接都可能是完整路径包含了文件夹,变量等。希望提取出其中的域名以便于进行深度分析。
我的CSV文件只有一列:

"http://www.pstips.net/diff-with-currentculture-and-currentuiculture.html"

"http://www.pstips.net/tag/powershell-v3"

"http://www.pstips.net/powershell-download-files.html"

"http://www.notelee.com/cs0012-the-type-system-object-is-defined-in-an-assembly-that-is-not-referenced.html"

"http://www.notelee.com/scom-create-wmi-perf-rule.html"

"http://www.lonsoon.com/2013/04/94.html"

"http://www.lonsoon.com/2013/05/101.html"

期望的输出结果:

www.pstips.net

www.pstips.net

www.pstips.net

www.notelee.com

www.notelee.com

www.lonsoon.com

www.lonsoon.com

分析:可以利用Import-csv命令,因为csv文件没有标题,需要临时指定标题。然后利用.NET中的类System.Uri

PS> Import-Csv .\file.csv -Header "link" | foreach  { ( [uri]($_.link) ).Host }

 

参考:

http://www.pstips.net/processing-text-1.html

 

本文出自 “Ricky's Blog” 博客,请务必保留此出处http://57388.blog.51cto.com/47388/1642625

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。