使用PowerShell,我想用MyValue替换给定文件中所有精确出现的[MYID]。最简单的方法是什么?


当前回答

(Get-Content file.txt) | 
Foreach-Object {$_ -replace '\[MYID\]','MyValue'}  | 
Out-File file.txt

注意(Get-Content file.txt)周围的括号是必需的:

Without the parenthesis the content is read, one line at a time, and flows down the pipeline until it reaches out-file or set-content, which tries to write to the same file, but it's already open by get-content and you get an error. The parenthesis causes the operation of content reading to be performed once (open, read and close). Only then when all lines have been read, they are piped one at a time and when they reach the last command in the pipeline they can be written to the file. It's the same as $content=content; $content | where ...

其他回答

用途(V3版本):

(Get-Content c:\temp\test.txt).replace('[MYID]', 'MyValue') | Set-Content c:\temp\test.txt

对于V2:

(Get-Content c:\temp\test.txt) -replace '\[MYID\]', 'MyValue' | Set-Content c:\temp\test.txt

对Set-Content命令的小修正。如果没有找到搜索的字符串,Set-Content命令将清空目标文件。

您可以首先验证要查找的字符串是否存在。否则,它将无法取代任何东西。

If (select-string -path "c:\Windows\System32\drivers\etc\hosts" -pattern "String to look for") `
    {(Get-Content c:\Windows\System32\drivers\etc\hosts).replace('String to look for', 'String to replace with') | Set-Content c:\Windows\System32\drivers\etc\hosts}
    Else{"Nothing happened"}

你可以尝试这样做:

$path = "C:\testFile.txt"
$word = "searchword"
$replacement = "ReplacementText"
$text = get-content $path 
$newText = $text -replace $word,$replacement
$newText > $path

因为这个经常出现,我为它定义了一个函数。我默认使用区分大小写、基于正则表达式的匹配,但我添加了针对文字文本和忽略大小写的开关。

# Find and replace text in each pipeline string.  Omit the -Replace parameter to delete
# text instead.  Use the -SimpleMatch switch to work with literal text instead of regular
# expressions.  Comparisons are case-sensitive unless the -IgnoreCase switch is used.
Filter Edit-String {
    Param([string]$Find, [string]$Replace='', [switch]$SimpleMatch, [switch]$IgnoreCase) 

    if ($SimpleMatch) {
        if ($IgnoreCase) {
            return $_.Replace($Find, $Replace,
                [System.StringComparison]::OrdinalIgnoreCase)
        }
        return $_.Replace($Find, $Replace)
    }
    if ($IgnoreCase) {
        return $_ -replace $Find, $Replace
    }
    return $_ -creplace $Find, $Replace
}

Set-Alias replace Edit-String
Set-Alias sc Set-Content  

使用

# 1 file
$f = a.txt; gc $f | replace '[MYID]' 'MyValue' -SimpleMatch | sc $f

# 0 to many files
gci *.txt | % { gc $_ | replace '\[MYID\]' 'MyValue' | sc $_ }

# Several replacements chained together
... | replace '[1-9]' T | replace a b -IgnoreCase | replace 'delete me' | ...

# Alias cheat sheet
#  gci Get-ChildItem
#  gc  Get-Content
#  sc  Set-Conent
#  %   ForEach-Object

我更喜欢使用。net的file类和它的静态方法,如下面的例子所示。

$content = [System.IO.File]::ReadAllText("c:\bla.txt").Replace("[MYID]","MyValue")
[System.IO.File]::WriteAllText("c:\bla.txt", $content)

这样做的优点是使用单个String,而不是像Get-Content那样使用String数组。这些方法还负责文件的编码(UTF-8 BOM等),而不需要您在大多数时候负责。

此外,与使用Get-Content和管道连接到Set-Content的算法相比,这些方法不会弄乱行结束符(可能会使用Unix行结束符)。

所以对我来说:几年下来会坏掉的东西更少。

在使用. net类时,一个鲜为人知的事情是,当您键入“[System.IO.”在PowerShell窗口中,您可以按Tab键来步进那里的方法。