【问题标题】:Use Powershell to Create Hash Table from .CSV File with Header使用 Powershell 从带有标题的 .CSV 文件创建哈希表
【发布时间】:2016-05-11 19:45:29
【问题描述】:

我有一个 .csv 文件(分隔符为 |),其中 AD 字段作为标题,字符串作为数据放入其中。我想从该 .csv 文件创建一个哈希表,其中列标题作为键,字符串信息作为数据。

这是文件格式:

LastName|FirstName|Office|Employeeid|BusinessTitle|CoreSector|Sector|CmbCorePractice|CmbPractice|Region|Committees|SectorLeaderRole|PracticeLeaderRole|AreaCountryRole|FirmLeaderShipRoleOne|FirmLeaderShipRole|generationQualifier|givenName|middlename|sn|extensionAttribute12|homePostalAddress|telephoneNumber|ipPhone|facsimileTelephoneNumber|mobile|homePhone|department|manager|assistant|extensionAttribute13
SMITH|JAMES|AMSTERDAM|0000000000|Leader|Healthcare|#|#|#|Europe|#|#|#|#|#|#|MR|JAMES|#|SMITH|#|#|+1 212 000 7692|0000|#|#|#|Knowledge Management|0001000000|#|#|#|#

数据以SMITH 开头,与LastName 对齐。

【问题讨论】:

  • 这将有助于我们查看:示例 CSV 数据(当然是混淆的),以及您已经尝试实现的代码(以及失败的地方)。
  • 但是为什么呢? :) 对象数组使用起来更容易、更安全(你知道 100% 确定哪些属性值属于一起)并且很容易使用 $ad = import-csv -path myfile.csv -delimiter "|" 导入
  • @FrodeF。 - 我最终想将 .csv 文件中的内容与 AD 中的内容进行比较,因此我只能使用文件中的内容更新 AD,因为文件是源文件,我认为哈希表是最好的做法。现在,我当前的脚本会遍历 .csv 文件并使用是否是新的信息更新 AD(文件和 AD 中的信息可能相同,但文件仍会覆盖 AD)。
  • 只要前后的值相同,覆盖属性是否重要? Set-ADUser -Replace $ht 需要属性和值的哈希表。将它放在哈希表与对象中没有任何区别,因为您仍然需要针对 AD 对象逐一检查属性并将更改添加到“attributestomodify”-哈希表。如果文件可能包含多个用户,则更有理由使用Import-CSV -Delimiter '|'。 :-)

标签: csv powershell hashtable


【解决方案1】:

这很简单。读取 CSV 的第一行以获取哈希表的键,如下所示:

$keys = (Get-Content 'C:\path\to\your.csv' -TotalCount 1) -split '\|'

或者像这样:

$keys = (Get-Content 'C:\path\to\your.csv' -TotalCount 1).Split('|')

接下来导入 CSV:

$csv = Import-Csv 'C:\path\to\your.csv' -Delimiter '|'

然后将 CSV 的列收集到一个哈希表中:

$ht = @{}
foreach ($key in $keys) {
  $ht[$key] = $csv | Select -Expand $key
}

【讨论】:

  • 谢谢@AnsgarWiechers 我尝试了您的脚本,但它似乎将键分解为单个字符。它看起来适用于第一条记录,但不适用于后续记录。我会附上源文件。
  • @allenr74:尝试使用-split '\|' 而不是-split '|'-split 运算符的分隔符参数被解释为正则表达式,因此为了使用文字 |,它必须是 \ -escaped。
【解决方案2】:

当我试图确定如何做类似的事情时,我偶然发现了这篇文章。我的目标也是从 CSV 的第一行中获取列名(感谢 Ansgar Wiechers' 为我解决此问题的出色答案)。 Ansgar's answer 创建一个哈希表,其中每个键的值是该键的所有值的数组。

出于我的目的,我需要一个数组,其中每个元素的值都是一个哈希表。即,数组的每个元素对应于原始 CSV 中的一行。这让我能够遍历 CSV 中的每条记录,然后遍历记录中的每一列。

由于 OP 对他最终需要其数据的格式的要求非常模糊,我想我会将我的解决方案作为对 Ansgar's 的补充发布。

请注意,为了适应 OP 的特定用例,只需将 $DELIM 的值从 , 更改为 |

# Constants.
$DELIM = ','
$CSV_F = 'file.csv'

# Parse keys
$keys = (gc "${CSV_F}" -TotalCount 1).Split($DELIM)
$csv = Import-CSV "${CSV_F}"
$data = @()

# Iterate through CSV to build array of hashtables.
ForEach ($r in $csv) {
    $tmp_h = @{}

    # Create hash of key-value pairs.
    ForEach($k in $keys) {
        $tmp_h[$k] = $r.($k)
    }

    # Add hash to array of hashes.
    $data += $tmp_h
}

# Display data
$data.ForEach({[PSCustomObject]$_}) | ft -AutoSize

给定file.csv中的以下示例数据:

RecordId,Name,Value
1,Alpha,Kilo
2,Bravo,Lima
3,Charlie,Mike
4,Delta,November
5,Echo,Oscar
6,Foxtrot,Papa
7,Golf,Quebec
8,Hotel,Romeo
9,India,Sierra
10,Juliet,Tango

将生成以下输出:

Name    Value    RecordId
----    -----    --------
Alpha   Kilo     1
Bravo   Lima     2
Charlie Mike     3
Delta   November 4
Echo    Oscar    5
Foxtrot Papa     6
Golf    Quebec   7
Hotel   Romeo    8
India   Sierra   9
Juliet  Tango    10

【讨论】:

    【解决方案3】:

    我想要与Doug's Answer 相同的结果,但以更紧凑的方式进行。 目标是从 csv 文件中读取数据,并能够为每一行添加属性,以便稍后在脚本中使用。

    $csv = Import-CSV file.csv
    $data = $csv| % {
         $row = @{};
         $_.psobject.Properties | % {$row[$_.name]= $_.value};
         $row;
    }
    
    

    【讨论】:

      猜你喜欢
      • 2013-11-09
      • 2017-10-15
      • 1970-01-01
      • 1970-01-01
      • 2017-04-12
      • 2021-05-29
      • 2011-07-01
      • 2011-10-24
      • 1970-01-01
      相关资源
      最近更新 更多