Powershell:使用哈希表替换字符串

时间:2011-09-18 14:01:53

标签: powershell replace hashtable

好的,所以我设置了一个哈希表,其中的名称是要替换的名称,键是要替换的内容,如下所示:

$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

3 个答案:

答案 0 :(得分:7)

这是一种方法:

$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循环;每个哈希表条目一次传递时,替换可以针对全文运行。

答案 1 :(得分:4)

根据您的文件和哈希表,您可以考虑各种优化:

  1. 您可以从哈希表键集合中构建正则表达式,如下所示:

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

    在执行此操作时,您不会迭代每个键,但现在您需要知道您匹配的键才能获得替换。另一方面,执行字符串替换而不是正则表达式替换(或更复杂的字符串拆分和连接过程)可能更快。

  2. 在Powershell中,您可以调用.NET Regex::Replace函数:

      

    string Replace(string input,System.Text.RegularExpressions.MatchEvaluator evaluationator)

    调用此方法,您可以使用如下的脚本块定义MatchEvaluator

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

    在scriptblock中,$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)
    
  5. 因此完整的脚本:

    $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
    

答案 2 :(得分:3)

我用这种方式工作

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