Powershell 用匹配覆盖文件内容而不是编辑单行
Powershell overwriting file contents with match instead of editing single line
我有一个文本文件,其中包含我要修改的字符串。
示例文本文件内容:
abc=1
def=2
ghi=3
如果我运行这个代码:
$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
结果是:
def=100
如果我像这样省略大于检查:
$a = (Get-Content $file) | %{
if($_ -match "def=(\d*)"){
$_ -replace "$($Matches[1])","$($MinX)"
}
}
$a
结果正确:
abc=1
def=100
ghi=3
我不明白在进行替换之前进行简单的整数比较怎么会把事情搞得这么糟,谁能告诉我我遗漏了什么?
那是因为表达式($Matches[1] -gt $MinX)
是一个字符串比较。在 Powershell 中,比较的左侧指示比较类型,因为它是类型 [string]
,Powershell 必须 cast/convert 表达式的右侧也为 [string]
.因此,您的表达式被评估为 ([string]$Matches[1] -gt [string]$MinX)
.
比较运算符 -gt
永远不会得到 $true 的值,因为您需要
- 首先将 $matches[1] string 值转换为 int,以便比较两个整数
2
永远不会大于 100
.. 将运算符更改为 -lt
。
- 您的代码只输出一行,因为您忘记输出与正则表达式不匹配的未更改行
$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
或使用 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
输出:
abc=1
def=100
ghi=3
我有一个文本文件,其中包含我要修改的字符串。
示例文本文件内容:
abc=1
def=2
ghi=3
如果我运行这个代码:
$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
结果是:
def=100
如果我像这样省略大于检查:
$a = (Get-Content $file) | %{
if($_ -match "def=(\d*)"){
$_ -replace "$($Matches[1])","$($MinX)"
}
}
$a
结果正确:
abc=1
def=100
ghi=3
我不明白在进行替换之前进行简单的整数比较怎么会把事情搞得这么糟,谁能告诉我我遗漏了什么?
那是因为表达式($Matches[1] -gt $MinX)
是一个字符串比较。在 Powershell 中,比较的左侧指示比较类型,因为它是类型 [string]
,Powershell 必须 cast/convert 表达式的右侧也为 [string]
.因此,您的表达式被评估为 ([string]$Matches[1] -gt [string]$MinX)
.
比较运算符 -gt
永远不会得到 $true 的值,因为您需要
- 首先将 $matches[1] string 值转换为 int,以便比较两个整数
2
永远不会大于100
.. 将运算符更改为-lt
。- 您的代码只输出一行,因为您忘记输出与正则表达式不匹配的未更改行
$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
或使用 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
输出:
abc=1
def=100
ghi=3