简体   繁体   English

Powershell 用匹配覆盖文件内容而不是编辑单行

[英]Powershell overwriting file contents with match instead of editing single line

I have a text file that contains a string I want to modify.我有一个文本文件,其中包含我要修改的字符串。

Example text file contents:示例文本文件内容:

abc=1
def=2
ghi=3

If I run this code:如果我运行此代码:

$file =  "c:\test.txt"
$MinX = 100
$MinY = 100

$a = (Get-Content $file) | %{
    if($_ -match "def=(\d*)"){
        if($Matches[1] -gt $MinX){$_ -replace "$($Matches[1])","$($MinX)" }
    }
}
$a

The result is:结果是:

def=100

If I omit the greater-than check like so:如果我像这样省略大于检查:

$a = (Get-Content $file) | %{
    if($_ -match "def=(\d*)"){
        $_ -replace "$($Matches[1])","$($MinX)"
    }
}
$a

The result is correct:结果是正确的:

abc=1
def=100
ghi=3

I don't understand how a simple integer comparison before doing the replace could screw things up so badly, can anyone advise what I'm missing?我不明白在进行替换之前进行简单的 integer 比较如何将事情搞砸,谁能告诉我我错过了什么?

That's because the expression ($Matches[1] -gt $MinX) is a string comparison.这是因为表达式($Matches[1] -gt $MinX)是一个字符串比较。 In Powershell, the left-hand side of a comparison dictates the comparison type and since that is of type [string] , Powershell has to cast/convert the right-hand side of the expression to [string] also.在 Powershell 中,比较的左侧指示比较类型,并且由于它是[string]类型,因此 Powershell 还必须将表达式的右侧强制转换/转换为[string] You expression, therefore, is evaluated as ([string]$Matches[1] -gt [string]$MinX) .因此,您的表达式被评估为([string]$Matches[1] -gt [string]$MinX)

The comparison operator -gt will never get you a value of $true because you need to比较运算符-gt永远不会为您提供 $true 的值,因为您需要

  • cast the $matches[1] string value to int first so it compares two integer numbers首先将 $matches[1]字符串值转换为 int 以便比较两个 integer 数字
  • 2 is never greater than 100 .. Change the operator to -lt instead. 2永远不会大于100 .. 将运算符更改为-lt
  • Your code outputs only one line, because you forgot to also output unchanged lines that do not match the regex您的代码仅输出一行,因为您也忘记了 output 与正则表达式不匹配的未更改行
$file = 'c:\test.txt'
$MinX = 100
$MinY = 100

$a = (Get-Content $file) | ForEach-Object {
    if ($_ -match '^def=(\d+)'){
        if([int]$matches[1] -lt $MinX){ $_ -replace $matches[1],$MinX }
    }
    else {
        $_
    }
}

$a

Or use switch (is also faster than using Get-Content):或者使用switch (也比使用 Get-Content 更快):

$file = 'c:\test.txt'
$MinX = 100
$MinY = 100

$a = switch -Regex -File $file {
    '^def=(\d+)' { 
        if([int]$matches[1] -lt $MinX){ $_ -replace $matches[1],$MinX }
    }
    default { $_ }
}

$a

Output: Output:

abc=1
def=100
ghi=3

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM