如何使用PowerShell从文件构造哈希表?

时间:2012-01-06 12:05:18

标签: regex powershell powershell-v2.0

我有一个文件,其中组件基线和组件名称存储如下

(Mailcomp@\My_PVOB) BL_2.1.0.9.5179@\My_PVOB
(OfficeComp@\My_PVOB) BL_2.1.0.17.6972@\MY_PVOB

实际上我需要构造一个哈希表,它可能有像

这样的条目
@(Key=Mailcomp,Value=BL_2.1.0.9.5179)
@(Key=OfficeComp, Value=BL_2.1.0.17.6972)

我试图替换如下

(Get-Content $BaselineFile) | foreach{ $_ -replace "@\My_PVOB[?]",''} | Out-File  $BaselineFile

然后我尝试创建哈希表,但第一个命令本身失败,我不知道如何从文件条目创建哈希表。有人可以帮助我吗?

3 个答案:

答案 0 :(得分:2)

假设你的$ baselinefile在预处理之后看起来像这样:

Mailcomp BL_2.1.0.9.5179
OfficeComp BL_2.1.0.17.6972

这应该有效:

$hash = @{}
Import-Csv $BaseLineFile -header "first", "second" -delimiter " " | ForEach-Object { $hash[$_.first] = $_.second}
$hash

答案 1 :(得分:2)

尝试一下:

Get-Content $BaselineFile | Foreach-Object { 
    if($_ -match '^\(([^@]+).+\)\s([^@]+)')
    {
        @{
            key=$matches[1]
            value=$matches[2]   
        }
    }
}

Name    Value
----    -----
value   BL_2.1.0.9.5179
key     Mailcomp
value   BL_2.1.0.17.6972
key     OfficeComp

或者

Get-Content $BaselineFile | Foreach-Object { 

    $value = ($_ -replace '@\\My_PVOB|\(|\)').split()

    @{
        key=$value[0]
        value=$value[1] 
    }
}

更新:创建一个哈希表,哈希键由第一个匹配组成,其值是第二个匹配:

$ht = @{}

Get-Content $BaselineFile | Foreach-Object {     

    if($_ -match '^\(([^@]+).+\)\s([^@]+)')
    {        
            $ht[$matches[1]] = $matches[2]     
    }    
}

$ht

Name       Value           
----       -----           
Mailcomp   BL_2.1.0.9.5179 
OfficeComp BL_2.1.0.17.6972

答案 2 :(得分:2)

在撰写本文时,有两个答案(一个来自Shay Levy,另一个来自jon Z),两个答案都很接近,但两者都不对 - 尽管Shay的答案已被接受( !)。这就是原因:

Shay代码的问题

Shay的答案过于文字,基于一个不准确的声明要求,该要求指定创建一个"哈希表,该表可能包含"这样:

@(Key=Mailcomp,Value=BL_2.1.0.9.5179)
@(Key=OfficeComp, Value=BL_2.1.0.17.6972)

但是如果要使用PowerShell语法,则表示错误。现实中的要求应如下所示:

@{Mailcomp=BL_2.1.0.9.5179}
@{OfficeComp=BL_2.1.0.17.6972}

也就是说,第一行指定Mailcomp的散列BL_2.1.0.9.5179的散列。 Shay代码的这个修改版本恰好提供了:

$hash = @{}
Get-Content $BaselineFile | 
Foreach-Object {
    if ($_ -match '^\(([^@]+).+\)\s([^@]+)')
    {
        $hash[$matches[1]]=$matches[2]
    }
}

这是输出:

Name       Value
----       -----
Mailcomp   BL_2.1.0.9.5179
OfficeComp BL_2.1.0.17.6972

这更容易使用,因为我现在可以访问$hash["Mailcomp"]$hash["OfficeComp"]来检索各自的值。

Shay的代码的第二个问题是哈希条目创建本身(@{ key=$matches[1]; value=$matches[2] })。该声明创建了一个单独的" mini"每次迭代的哈希表(即输入的每一行)。只有似乎才能产生合理的输出,因为他的代码中隐式写输出的合并。为了证明这一点 - 并且比较苹果和苹果 - 采用我的代码并用等效的Shay代码替换条件:

    if ($_ -match '^\(([^@]+).+\)\s([^@]+)')
    {
        @{ $matches[1]=$matches[2] }
    }

您会发现$hash["Mailcomp"] 会返回预期的BL_2.1.0.9.5179

Jon代码的问题

我喜欢jon Z的回答;我真的这样做。真。但它让我想起了一个很棒的老笑话assume we have a can opener...这是一个非常好的解决方案,当且仅当输入适合简单的分隔符时。不是这里的情况 - 按摩输入需要正则表达式(或其他机制)。平心而论,Jon明确指出他正在进行一些预处理。 “努夫说。