【问题标题】:Reading list style text file into powershell array将列表样式文本文件读入powershell数组
【发布时间】:2019-07-08 12:53:42
【问题描述】:

我提供了一个文本文件中的字符串块列表,我需要将它放在 powershell 中的数组中。

列表如下所示

a:1
b:2
c:3
d:
e:5
[blank line]
a:10
b:20
c:30
d:
e:50
[blank line]
... 

我希望它在一个 powershell 数组中进一步使用它。

我正在使用

$output = @()

Get-Content ".\Input.txt" | ForEach-Object {

    $splitline = ($_).Split(":")

    if($splitline.Count -eq 2) {

        if($splitline[0] -eq "a") {
            #Write-Output "New Block starting"
            $output += ($string)
            $string = "$($splitline[1])"

        } else {

            $string += ",$($splitline[1])"
        }
    }    
}

Write-Host $output -ForegroundColor Green

$output | Export-Csv ".\Output.csv" -NoTypeInformation
$output | Out-File ".\Output.txt"

但这整件事感觉很麻烦,而且输出不是 csv 文件,在这一点上我认为是因为我使用数组的方式。 Out-File 确实会生成一个文件,其中包含用逗号分隔的行。

也许有人可以推动我朝着正确的方向前进。

谢谢 x

【问题讨论】:

  • 如果你需要一个 csv 文件,为什么要先将其转换为数组??无论如何,如果你需要一个 csv,你需要添加一个标题并将其转换回文本......然后导出到 csv ...

标签: list powershell file text


【解决方案1】:

一种解决方案是将您的数据转换为可读取到自定义对象的哈希表数组。然后可以根据需要导出、格式化或读取输出数组对象。

$hashtables = (Get-Content Input.txt) -replace '(.*?):','$1=' | ConvertFrom-StringData
$ObjectShell = "" | Select-Object ($hashtable.keys | Select-Object -Unique)

$output = foreach ($hashtable in $hashtable) {
  $obj = $ObjectShell.psobject.Copy()
  foreach ($n in $hashtable.GetEnumerator()) {
    $obj.($n.key) = $n.value
  }
  $obj
}
$output
$output | Export-Csv Output.csv -NoTypeInformation

说明:

每行的第一个冒号 (:) 被替换为 =。这使ConvertFrom-StringData 能够创建一个哈希表数组,其中= 的LHS 上的值是键,= 的RHS 上的值是值。如果你知道每一行只有一个:,你可以让-replace的操作更简单。

$ObjectShell 只是一个具有您的数据所呈现的所有属性的对象。无论您是否为它们分配值,您都需要为每行数据提供所有属性。否则,控制台中的 CSV 输出或表格视图将出现问题。

第一个 foreach 遍历 $hashtables 数组。然后我们需要遍历每个哈希表来找到键和值,这是由第二个foreach循环执行的。每个键/值对都存储为$ObjectShell 的副本。 .psobject.Copy() 方法用于防止对原始对象的引用。更新引用的数据将更新原始对象的数据。

$output 包含所有已处理数据的对象数组。

输出的可用性:

# Console Output

$output | format-table

a  b  c  d e
-  -  -  - -
1
   2
      3

           5

10
   20
      30

           50

# Convert to CSV

$output | ConvertTo-Csv -NoTypeInformation
"a","b","c","d","e"
"1",,,,
,"2",,,
,,"3",,
,,,"",
,,,,"5"
,,,,
"10",,,,
,"20",,,
,,"30",,
,,,"",
,,,,"50"

# Accessing Properties

$output.b
2
20

$output[0],$output[1]

a : 1
b :
c :
d :
e :

a :
b : 2
c :
d :
e :

替代转换:

$output = ((Get-Content Input.txt -raw) -split "(?m)^\r?\n") | Foreach-Object { 
  $data = $_ -replace "(.*?):(.*?)(\r?\n)",'"$1":"$2",$3'
  $data = $data.Remove($data.LastIndexOf(','),1)
  ("{1}`r`n{0}`r`n{2}" -f $data,'{','}') | ConvertFrom-Json
}
$output | ConvertTo-Csv -NoType

另类解释:

由于ConvertFrom-StringData 不保证哈希表键顺序,因此此替代方法准备文件以进行 JSON 转换。如果每个组的顺序相同,这将保持文件中列出的属性顺序。否则,将尊重第一组的属性顺序。

所有属性及其各自的值除以每行的第一个 : 字符。属性和值都用双引号括起来。每个属性行由, 分隔。然后最后添加了开头{ 和关闭}。生成的 JSON 格式字符串将转换为自定义对象。

【讨论】:

  • 这几乎是完美的,因为文件中的空白行确实表示一组新对象,是否可以让它看起来像 Header: "a","b","c ","d","e" 第 1 行:"1","2","3",,"5"
  • @xBarns,我在帖子底部添加了一个替代转换。看看这是否符合您的要求。
  • 这正是我想要的!
【解决方案2】:

你可以用\n换行分割,见例子:

$text = @"
a:1
b:2
c:3
d:
e:5

a:10
b:20
c:30
d:
e:50
e:50
e:50

e:50
"@

$Array = $text -split '\n' | ? {$_}
$Array.Count
15

如果要排除空行,​​请添加? {$_}

以你的例子:

$Array = (Get-Content ".\Input.txt") -split '\n' | ? {$_}

【讨论】:

  • 使用 -split '\r?\n',因为在 Windows 中,换行符是使用两个字符 CR 和 LF 构造的。
  • 也许我表达自己错了,这不是拆分行,而是将其转换为列格式,因此 a 的所有值在一个列中,b 在下一列中,a.s.o.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
  • 2018-12-03
  • 2017-07-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多