Как да конструирам хеш таблица от файл с помощта на powershell?

Имам файл, в който базовата линия на компонента и имената на компонентите се съхраняват, както следва

(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

След това се опитах да създам хеш таблица, но самата първа команда се провали и не знам как да създам хеш таблица от записи във файла. Може ли някой да ми помогне, моля?


person Samselvaprabu    schedule 06.01.2012    source източник


Отговори (3)


Към момента на писане има два отговора (един от Shay Levy и един от jon Z), които са близки, но нито един не е съвсем правилен - въпреки факта, че отговорът на 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] }). Това изявление създава отделна "мини" хеш-таблица за всяка итерация (т.е. всеки ред на входа). Само изглежда произвежда разумен изход поради обединяването на неявния Write-Output в неговия код. За да докажете това – и за да сравните ябълки с ябълки – вземете моя код по-горе и заменете условното с този еквивалент на кода на Шей:

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

Ще откриете, че $hash["Mailcomp"] не връща очакваното BL_2.1.0.9.5179.

Проблеми с кода на Джон

Харесвам отговора на jon Z; Наистина. Наистина ли. Но това ми напомня за страхотната стара шега с ключовата линия да приемем, че имаме отварачка за консерви. .. Това е много добро решение, ако и само ако входът е податлив на прост разделител. Тук случаят не е такъв - необходим е регулярен израз (или друг механизъм) за масажиране на входа. Честно казано, Джон отбелязва, че изрично като заявява, че предполага известна предварителна обработка. — каза Наф.

person Michael Sorens    schedule 10.01.2012
comment
Ще проверя и ще направя необходимата промяна, за да приема най-добрия отговор - person Samselvaprabu; 10.01.2012

Ако приемем, че вашият $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
person jon Z    schedule 06.01.2012

Опитайте това:

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

Or

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
person Shay Levy    schedule 06.01.2012
comment
Отново лесните за разбиране отговори на Леви са разтърсващи. Работи приятелю и също е разбираемо - person Samselvaprabu; 06.01.2012
comment
Това е неназован хеш. Как да съхраня това в именуван хеш? Така че мога да обработя всяка стойност в хеш и да направя още една операция - person Samselvaprabu; 06.01.2012
comment
Можете да присвоите резултата на променлива и да обработите всяка от тях, като използвате нейния колекторски индекс. като: $h = gc... и след това $h[0].key и т.н - person Shay Levy; 06.01.2012
comment
Приятелю, както споменава msorens, вашият код има ли проблем? Използвах метода за замяна от вашия код и останалите неща, които използвам от JonZ, и не съм сигурен в тази теория - person Samselvaprabu; 10.01.2012