使用Powershell替换regex结果的子部分

使用Powershell替换regex结果的子部分,regex,string,powershell,replace,Regex,String,Powershell,Replace,使用Powershell,我知道如何使用正则表达式搜索文件中的复杂字符串,并将其替换为某个固定值,如以下代码段所示: Get-ChildItem "*.txt" | Foreach-Object { $c = ($_ | Get-Content) $c = $c -replace $regexA,'NewText' [IO.File]::WriteAllText($_.FullName, ($c -join "`r`n")) } 现在,我试图找出如何替换正则表达式中每

使用Powershell,我知道如何使用正则表达式搜索文件中的复杂字符串,并将其替换为某个固定值,如以下代码段所示:

Get-ChildItem  "*.txt" |
Foreach-Object {
    $c = ($_ | Get-Content)
    $c = $c -replace $regexA,'NewText'
    [IO.File]::WriteAllText($_.FullName, ($c -join "`r`n"))
}
现在,我试图找出如何替换正则表达式中每个匹配项的一个子段。这能像上面那样一步顺利地完成吗?或者,您必须提取较大正则表达式的每个匹配项,在其中搜索并替换,然后以某种方式将结果粘贴回原始文本中吗

为了举例说明,假设在下面的测试文本中,我只想在下面的文本中找到编号为14xx的实例,如“test=*1404”,并将14xx替换为16xx

A 2180 1830 12 0 3 3 TEST=C1404
A 900 1830 12 0 3 3 TEST=R1413
A 400 1830 12 0 3 3 TEST=R1411
A 1090 1970 12 0 3 3 TEST=U1400
A 1090 1970 12 0 3 3 TEST=CSA1400
A 1090 1970 12 0 3 3 TEST=CSA1414
A 1090 1970 12 0 3 3 TEST=CSA140
A 1090 1970 12 0 3 3 TEST=CSA14001
A 1090 1970 12 0 3 3 TEST=CSA17001
也就是说,我希望生成的文本如下所示,您会注意到只有前6行应该更改:

A 2180 1830 12 0 3 3 TEST=C1604
A 900 1830 12 0 3 3 TEST=R1613
A 400 1830 12 0 3 3 TEST=R1611
A 1090 1970 12 0 3 3 TEST=U1600
A 1090 1970 12 0 3 3 TEST=CSA1600
A 1090 1970 12 0 3 3 TEST=CSA1614 <- Second instance of '14' shouldn't change
A 1090 1970 12 0 3 3 TEST=CSA140 <- Shorter numbers shouldn't change
A 1090 1970 12 0 3 3 TEST=CSA14001 <- Longer numbers shouldn't change
A 1090 1970 12 0 3 3 TEST=CSA17001
我宁愿不必硬编码一个详尽的列表,其中可以包含在“=”和数字之间的东西,比如“R”、“C”、“CSA”等等


我已经做了一个小时左右的工作,在那里我得到了正则表达式的所有匹配项,在其中搜索以16替换14,然后用新旧值在原始文本上运行replace,例如
replace($myText,“TEST=CSA1400”,“TEST=CSA1600”)
,但这并不能很好地覆盖特殊情况,感觉就像是我在往兔子洞里走

您需要对要保留的子表达式进行分组(即将它们放在括号之间),然后通过替换字符串中的变量
$1
$2
引用这些组。试着这样做:

$regexA = '( TEST=[A-Za-z]+)14(\d\d)$'

Get-ChildItem '*.txt' | ForEach-Object {
    $c = (Get-Content $_.FullName) -replace $regexA, '${1}16$2' -join "`r`n"
    [IO.File]::WriteAllText($_.FullName, $c)
}
试试这个:

Get-ChildItem  "*.txt" |
Foreach-Object {
  $c = $_ | Get-Content | Foreach {$_ -replace '(?<=TEST=\D+)14(?=\d{2}(\D+|$))','16'}
  $c | Out-File $_.FullName -Enc Ascii
}
获取子项“*.txt”|
Foreach对象{

$c=$124; Get Content | Foreach{$124;-replace'(?下面是一个使用scriptblock委托(有时称为计算器)的示例):


可以说,它比-replace运算符更复杂,但允许您使用powershell运算符来构造替换文本,这样您就可以在脚本块中执行任何操作。

+1我对逃避该替换操作感到头疼。在您的方法中,将
-raw
添加到
获取内容是否存在任何危险取消>并从替换部件中删除
连接
。@SSilk也应该可以,但您需要将正则表达式中的
$
替换为类似
(\r |$)另一个后续问题:如果我在中间粘贴的值本身是另一个变量,在正则表达式之外,而不是固定值。例如,如果在示例代码中<代码> 16代码/代码>是一些变量<代码> $编号/代码>,那么我需要做些什么才能使它被识别?当我用代码尝试它时,它确实打印出来了。用
$
替换变量名。@SSilk如果要在替换字符串中使用正则变量,则需要使用双引号而不是单引号,并从正则表达式中转义引用组的变量:
“`$1$number`$2”
$f=$\u.FullName;(获取内容$f)-replace…| Out File$f…
可能是一种更优雅的方法&
Get-ChildItem  "*.txt" |
Foreach-Object {
  $c = $_ | Get-Content | Foreach {$_ -replace '(?<=TEST=\D+)14(?=\d{2}(\D+|$))','16'}
  $c | Out-File $_.FullName -Enc Ascii
}
$regex = [regex]'( TEST=\D+)14(\d{2})\s*$'
$evaluator = { '{0}16{1}' -f $args[0].Groups[1..2] }
filter set-number { $regex.Replace($_, $evaluator) }

foreach ($file in Get-ChildItem  "*.txt")
 {
   ($file | get-content) | set-number | Set-Content $file.FullName
 }