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
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这是一种方法:
您看到每一行三次的原因是由于嵌套的 foreach 循环。文件中每一行的每个哈希表条目都运行一次替换操作。这不会更改源文件,但默认情况下它会输出替换的结果(即使没有任何更改)。
您可以通过首先将文件读入变量,然后使用循环替换来更新该变量来获得所需的功能。您也不需要为文件内容使用单独的 foreach 循环;替换可以针对每个哈希表条目一次性运行全文。
Here's one way to do it:
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.
我是这样工作的
I got it work this way
根据您的文件和哈希表,您可以考虑各种优化:
您可以从哈希表键集合构建正则表达式,如下所示:
在执行此操作时,您不会迭代每个键,但现在您需要知道匹配哪个键才能获得替换。另一方面,进行字符串替换而不是正则表达式替换(或者更复杂的字符串拆分和连接过程)可能会更快。
在 Powershell 中,您可以调用 .NET
Regex::Replace
函数:<块引用>
字符串替换(字符串输入,System.Text.RegularExpressions.MatchEvaluator评估器)
调用此方法,您可以使用脚本块定义一个
MatchEvaluator
,如下所示:在脚本块中,
$args[0]
是一个System.Text.RegularExpressions.Match
,因此您可以使用其Value
属性索引到$r
哈希表。Get-Content
返回一个字符串数组,这对于-replace
运算符来说很好,但也意味着运行额外的循环。[System.IO.File]::ReadAllText
将返回单个字符串,因此正则表达式只需要解析一次。如果您使用
Get-Content
,要使用$regex.Replace
(而不是-replace
),您将需要一个循环:< /p>因为我不是,所以我可以使用单个替换调用:
因此完整的脚本:
Depending on your file and hashtable, there are various optimizations you could consider:
You may be able to build a regex from the hashtable key collection like so:
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).
In Powershell you can call the .NET
Regex::Replace
function:Calling this method you can define a
MatchEvaluator
with a scriptblock like so:In the scriptblock,
$args[0]
is aSystem.Text.RegularExpressions.Match
, so you can use itsValue
property to index into the$r
hashtable.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.If you used
Get-Content
, to use$regex.Replace
(instead of-replace
) you would need a loop:Since I am not I can use a single replace call:
Thus the full script: