2011-09-18 73 views
3

好了替換字符串,所以我給自己定了一個哈希表的名字是什麼,以取代和鑰匙是做什麼用代替,就像這樣:PowerShell的:使用哈希表

$r = @{ 
    "dog" = "canine"; 
    "cat" = "feline"; 
    "eric" = "eric cartman" 
} 

我應該怎麼辦下一個?我試過這個:

(Get-Content C:\scripts\test.txt) | Foreach-Object { 
    foreach ($e in $r.GetEnumerator()) { 
     $_ -replace $e.Name, $e.Value 
    } 
} | Set-Content C:\scripts\test.txt.out 

但它根本不起作用,它只是每行寫三次而不替換任何東西。

編輯:test.txt的包含:

dog 
cat 
eric 

test.txt.out:

dog 
dog 
dog 
cat 
cat 
cat 
eric 
eric 
eric 
+0

什麼是C的含量:\腳本\ test.txt的? –

回答

6

下面是做這件事:

$file = Get-Content C:\scripts\test.txt 
foreach ($e in $r) { 
    $file = $file -replace $e.Name, $e.Value 
} 
Set-Content -Path C:\scripts\test.txt.out -Value $file 

你的理由每行看三次是因爲嵌套的foreach循環。對於文件中的每一行,每個散列表項都會運行一次替換操作。這不會更改源文件,但默認情況下它會輸出替換的結果(即使沒有任何更改)。

您可以通過首先將文件讀入變量,然後使用循環替換來更新該變量來獲得所需的功能。你也不需要單獨的文件內容的foreach循環;替換可以針對每個哈希表項一次傳遞全文。

+0

的foreach($在R $ E)工程,以及$ r.GetEnumerator()。 –

+0

謝謝!像魅力一樣工作。 – khvn

+0

好點@Christian,GetEnumerator()調用並沒有真正完成任何事情。刪除。 – ajk

2

我得到了它以這種方式工作

foreach ($i in $HashTable.Keys) { 
    $myString = $myString -replace $i, $HashTable[$i] 
} 
3

根據您的文件和哈希表,有各種優化,你可以考慮:

  1. 您可以從哈希表中建立一個正則表達式這樣的密鑰集合:

    $regexes = $r.keys | foreach {[System.Text.RegularExpressions.Regex]::Escape($_)} 
    $regex = [regex]($r.Keys -join '|')  
    

    在這樣做,你不會迭代每個鍵,但n你需要知道你匹配哪個鍵才能獲得替換。另一方面,執行字符串替換可能會更快,而不是正則表達式替換(或者像字符串拆分和聯接過程那樣更復雜)。

  2. 在PowerShell中,你可以調用.NET Regex::Replace功能:

    字符串替換(字符串輸入,System.Text.RegularExpressions.MatchEvaluator評估)

    調用此方法可以定義一個MatchEvaluator,象這樣一個腳本塊:

    $callback = { $r[$args[0].Value] } 
    

    在腳本塊,$args[0]System.Text.RegularExpressions.Match,因此您可以使用其Value屬性來索引$r散列表。

  3. Get-Content返回一個字符串數組,這對-replace運算符來說很好,但也意味着一個額外的循環運行。 [System.IO.File]::ReadAllText將返回一個單一的字符串,所以正則表達式只需要解析一次。

    $file = [System.IO.File]::ReadAllText("C:\scripts\test.txt") 
    
  4. 如果使用Get-Content,使用$regex.Replace(而不是-replace),您將需要一個循環:

    $file = $file | % { $regex.Replace($_, $callback) } 
    

    因爲我不是我可以用一個單一的替代呼叫:

    $file = $regex.Replace($file, $callback) 
    

因此完整腳本:

$r = @{ 
    "dog" = "canine"; 
    "cat" = "feline"; 
    "eric" = "eric cartman" 
} 


$regexes = $r.keys | foreach {[System.Text.RegularExpressions.Regex]::Escape($_)} 
$regex = [regex]($regexes -join '|') 

$callback = { $r[$args[0].Value] } 

$file = [System.IO.File]::ReadAllText("C:\scripts\test.txt") 
$file = $regex.Replace($file, $callback) 
Set-Content -Path C:\scripts\test.txt.out -Value $file 
+1

爲了使它不區分大小寫,使用'$正則表達式= [正則表達式( 「(我)?」 +($正則表達式-join '|'))' – sparebytes