【问题标题】:How to capture data from a text file with line breaks in Powershell如何在 Powershell 中从带有换行符的文本文件中捕获数据
【发布时间】:2014-03-20 19:17:32
【问题描述】:

我有大量的文本文件,我正试图将其解析到 powershell 中,但似乎无法找到一种方法来做我所追求的。我基本上将长文本文件与数据组放在一起并用换行符分隔。所有分组在一起的数据都属于一起,本质上需要转换为 powershell 对象或数组进行操作。我不需要任何帮助来处理数据,我只需要一种将数据分成块的方法。例如,一个文本文件可能类似于

group=name1
member=user1
member=user2
member=user3

group=name2
member=user1
member=user4
member=user5

group=name3
member=user1
member=user2

group=name4
member=user2
member=user4
member=user5
member=user6

我只需要一种方法通过 get-content 将其拉入 powershell,并且只要换行符到达新对象或需要创建/完成以存储新数据的任何内容。我能够实现我所追求的,但只是在花费大量时间将 xml 标签添加到需要 waaaay 很长时间的所有内容之后。任何方向或帮助将不胜感激。

【问题讨论】:

  • 这个文件有多大,你用的是什么版本的Powershell?
  • 足够大,足够多,我不想花时间修改源文件。我正在使用 powershell v3。

标签: powershell powershell-2.0 powershell-3.0


【解决方案1】:
  • 有一个组的哈希表。
  • 遍历文件内容。
    • 当您点击“group=”行时,将组名添加到哈希表中,指向一个新数组。
    • 当您点击“member=”行时,将名称添加到组数组中。

例如

$groups = @{}

foreach ($line in Get-Content .\t.txt) {
    if ($line -match "group") {
        $current_group = $line.Split("=")[1]
        $groups[$current_group] = @()
    }
    if ($line -match "member") {
        $name = $line.Split("=")[1]
        $groups[$current_group] += $name
    }
}

write $groups

您发布的输入的示例输出:

Name                           Value                                                                                      
----                           -----                                                                                      
name1                          {user1, user2, user3}                                                                      
name2                          {user1, user4, user5}                                                                      
name3                          {user1, user2}                                                                             
name4                          {user2, user4, user5, user6}  

然后你可以使用$groups.keys列出所有组,$groups['name1']直接获取它们等等。

【讨论】:

  • 这是个不错的选择。我唯一的问题是是否有另一种方法,因为并非所有文本文件都与我给出的句法示例匹配。文件之间的共同元素是换行符。但这是一个很好的起点。
  • @DoS 可能还有其他方法,但是这个原则是为一个组保留一个数据存储,将每一行添加到其中,然后当你到达一个空白行时,将处理过的数据块存储在某个地方并且为下一行开始一个新的空行,这应该适用于很多情况。您需要从线路中获取哪些数据以及如何将它们添加到存储中将会发生变化。也许您还需要另一个级别和每个文件的数据存储区?
【解决方案2】:

由于您需要对象,这里有另一个选项(需要 V3 用于 [ordered] 和 [PSCustomObject] 类型加速器:

#Define a script block to create an empty hash table for object schema
$NewHT = {
 $HT = 
 [ordered]@{
   Group = ''
   Members = New-Object collections.arraylist
  }
}

#Dot source the script block to create a new hash table
.$NewHT

#Create objects from input
$NewObjects = 
Switch -Regex (Get-Content file.txt)
{
  '^Group='    { $HT.Group = $_.split('=')[1] }

  '^Member='   { [void]$HT.Members.Add($_.split('=')[1]) }

  '^\s*$'      {
                 if ($HT.Group)
                  {
                   [PSCustomobject]$HT
                   .$NewHT
                  }
               }

  Default      {Write-Warning "Unrecognized line: `n`n $_"}
}

使用您发布的数据的结果:

 $NewObjects | ft -AutoSize

Group Members              
----- -------              
name1 {user1, user2, user3}
name2 {user1, user4, user5}
name3 {user1, user2} 

该模式应该适用于您描述的具有空行分隔组的任何文件,并且在创建对象之前不需要对分组数据进行任何临时存储即可生成对象。一旦所有必需的数据可用,就会创建对象。

【讨论】:

  • 另一个可靠的答案。你们说得对。我喜欢这两个答案,但我想我可能希望最初的摄取更通用一点,以便它可以重复使用。从那里我可以将它用作函数或脚本,然后在第二步中切碎实际信息以对其进行修改并吐出所需的信息。我倾向于做更多的oop,并用类等来思考这个问题,并且可能会过度思考/使这个问题复杂化。但到目前为止给出的两个答案都符合我的需要。我肯定会投票给他们两个。
猜你喜欢
  • 2013-12-30
  • 1970-01-01
  • 1970-01-01
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
  • 2016-12-22
  • 1970-01-01
  • 2010-09-22
相关资源
最近更新 更多