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

发布于 2024-12-05 08:00:33 字数 580 浏览 1 评论 0原文

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

$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

Okay, so I've set up a hash table with names being what to replace and keys being what to replace with, like this:

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

What should I do next? I've tried this:

(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

But it doesn't work at all, it just writes each line three times, without replacing anything.

EDIT: Contains of test.txt:

dog
cat
eric

test.txt.out:

dog
dog
dog
cat
cat
cat
eric
eric
eric

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

胡渣熟男 2024-12-12 08:00:33

这是一种方法:

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

Here's one way to do it:

$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

The reason you were seeing each line three times is because of the nested foreach loop. A replace operation was running once per hashtable entry for every line in the file. That doesn't change the source file, but by default it does output the result of the replace (even if nothing is changed).

You can get the desired functionality by reading the file into a variable first, and then using your looping replace to update that variable. You also don't need a separate foreach loop for the file contents; the replace can run against the full text in one pass per hashtable entry.

云之铃。 2024-12-12 08:00:33

我是这样工作的

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

I got it work this way

foreach ($i in $HashTable.Keys) {
  $myString = $myString -replace $i, $HashTable[$i]
}
半城柳色半声笛 2024-12-12 08:00:33

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

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

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

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

  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),您将需要一个循环:< /p>

    $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

Depending on your file and hashtable, there are various optimizations you could consider:

  1. You may be able to build a regex from the hashtable key collection like so:

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

    In doing this you wouldn't to iterate every key, but now you need to know which key you matched in order to get the replacement. On the other hand, it may be faster to do string replacement instead of regex replacement (or something more complex like a string split and join process).

  2. In Powershell you can call the .NET Regex::Replace function:

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

    Calling this method you can define a MatchEvaluator with a scriptblock like so:

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

    In the scriptblock, $args[0] is a System.Text.RegularExpressions.Match, so you can use its Value property to index into the $r hashtable.

  3. Get-Content returns an array of strings which is fine for the -replace operator, but also implies an extra loop running. [System.IO.File]::ReadAllText will instead return a single string, so the regex only needs to be parsed once.

    $file = [System.IO.File]::ReadAllText("C:\scripts\test.txt")
    
  4. If you used Get-Content, to use $regex.Replace (instead of -replace) you would need a loop:

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

    Since I am not I can use a single replace call:

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

Thus the full script:

$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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文