Powershell - 替换字符串中的多个 5 位子字符串
Powershell - Replace multiple 5-digit substrings in a string
我们有一些客户在支付发票时没有提及我们的 INV 前缀,因此我想将其添加到我们的 MT940 银行对帐单文件中。
:20: :25:MHAZNL2AXXX/0376603160 :28C:102/ :60F:C220525EUR5000,
:61:2204130413C336,52NMSCTOPF2500472627//GBBR001SCT TOPF2500472627
:86:17136 17364 17382 032022102402 WONG TONG SARL 1 RUESOMETHINGPARIS
SOGEFRPPXXX NOT PROVIDED
:61:2204200420C406,02NMSCTOPF2500479378//GBCJ005SCT TOPF2500479378
:86:17486 17586 17697 17813 0320221054201 WONG TONG SARL 1RUE
SOMETHINGPARIS SOGEFRPPXXX NOTPROVIDED
我需要它
:20: :25:MHAZNL2AXXX/0376603160 :28C:102/ :60F:C220525EUR5000,
:61:2204130413C336,52NMSCTOPF2500472627//GBBR001SCT TOPF2500472627
:86:INV17136 INV17364 INV17382 032022102402 WONG TONG SARL 1
RUESOMETHINGPARIS SOGEFRPPXXX NOT PROVIDED
:61:2204200420C406,02NMSCTOPF2500479378//GBCJ005SCT TOPF2500479378
:86:INV17486 INV17586 INV17697 INV17813 0320221054201 WONG TONG SARL
1RUE SOMETHINGPARIS SOGEFRPPXXX NOTPROVIDED
我也使用 switch 语句来匹配其他行,这就是我使用 switch 的原因。
switch -Regex -File c:\Temp\WONG.ged {
':86:.+WING SENG.+' { $_.replace('([1234567]\d{4}[ ])', "INV") }
default { $_ } # unrelated line, pass through
}
这似乎 work 但替换不起作用(如果我将 WONG 替换为 TEST 那么它就可以正常工作)。
我加了1234567防止匹配太多还是匹配太多
这里有几个问题:
- 您需要使用支持正则表达式替换操作的
-replace
运算符,而不是 String.Replace
方法(参见 What's the difference between .replace and -replace in powershell?)
- 您的文本不包含
WING SENG
,因此没有匹配项
- 定义反向引用时,需要使用文字
$
,因此要么使用单引号括起替换 'INV'
,要么转义反引号 "INV`"
。
这将产生预期的结果:
switch -Regex -File c:\Temp\WONG.ged {
':86:.+WONG TONG' { $_ -replace '[1-7]\d{4} ', 'INV$&' }
default { $_ } # unrelated line, pass through
}
注意模式看起来有点不同:[1-7]
比冗长的 [1234567]
更短更精简,并且不需要用捕获组包围整个模式,您可以参考与 $&
反向引用的整体匹配。此外,无需在正则表达式末尾添加 .+
。
还有一个替代解决方案:
(Get-Content $filepath) -replace '(\G(?!^)|^(?=:86:.+WONG TONG))(.*?)([1-7]\d{4}(?!\S))', 'INV'
参见regex demo。 详情:
(\G(?!^)|^(?=:86:.+WONG TONG))
- 第 1 组:上一个成功匹配的结尾 (\G(?!^)
) 或 (|
) 字符串(此处为行)开始位置 (^
) 紧跟 :86:
,换行字符以外的任何一个或多个字符,尽可能多,然后是 WON TONG
string
(.*?)
- 第 2 组 (</code>):除换行字符外的任何零个或多个字符尽可能少</li>
<li><code>([1-7]\d{4}(?!\S))
- 第 3 组 (</code>):从 <code>1
到 7
的数字,然后是字符串末尾或紧随其后的任意四位数字有一个空格。
(Get-Content $filepath)
逐行读取文件,所以任何不匹配的行将原样输出,不受影响。
我们有一些客户在支付发票时没有提及我们的 INV 前缀,因此我想将其添加到我们的 MT940 银行对帐单文件中。
:20: :25:MHAZNL2AXXX/0376603160 :28C:102/ :60F:C220525EUR5000,
:61:2204130413C336,52NMSCTOPF2500472627//GBBR001SCT TOPF2500472627
:86:17136 17364 17382 032022102402 WONG TONG SARL 1 RUESOMETHINGPARIS SOGEFRPPXXX NOT PROVIDED
:61:2204200420C406,02NMSCTOPF2500479378//GBCJ005SCT TOPF2500479378
:86:17486 17586 17697 17813 0320221054201 WONG TONG SARL 1RUE SOMETHINGPARIS SOGEFRPPXXX NOTPROVIDED
我需要它
:20: :25:MHAZNL2AXXX/0376603160 :28C:102/ :60F:C220525EUR5000,
:61:2204130413C336,52NMSCTOPF2500472627//GBBR001SCT TOPF2500472627
:86:INV17136 INV17364 INV17382 032022102402 WONG TONG SARL 1 RUESOMETHINGPARIS SOGEFRPPXXX NOT PROVIDED
:61:2204200420C406,02NMSCTOPF2500479378//GBCJ005SCT TOPF2500479378
:86:INV17486 INV17586 INV17697 INV17813 0320221054201 WONG TONG SARL 1RUE SOMETHINGPARIS SOGEFRPPXXX NOTPROVIDED
我也使用 switch 语句来匹配其他行,这就是我使用 switch 的原因。
switch -Regex -File c:\Temp\WONG.ged {
':86:.+WING SENG.+' { $_.replace('([1234567]\d{4}[ ])', "INV") }
default { $_ } # unrelated line, pass through
}
这似乎 work 但替换不起作用(如果我将 WONG 替换为 TEST 那么它就可以正常工作)。 我加了1234567防止匹配太多还是匹配太多
这里有几个问题:
- 您需要使用支持正则表达式替换操作的
-replace
运算符,而不是String.Replace
方法(参见 What's the difference between .replace and -replace in powershell?) - 您的文本不包含
WING SENG
,因此没有匹配项 - 定义反向引用时,需要使用文字
$
,因此要么使用单引号括起替换'INV'
,要么转义反引号"INV`"
。
这将产生预期的结果:
switch -Regex -File c:\Temp\WONG.ged {
':86:.+WONG TONG' { $_ -replace '[1-7]\d{4} ', 'INV$&' }
default { $_ } # unrelated line, pass through
}
注意模式看起来有点不同:[1-7]
比冗长的 [1234567]
更短更精简,并且不需要用捕获组包围整个模式,您可以参考与 $&
反向引用的整体匹配。此外,无需在正则表达式末尾添加 .+
。
还有一个替代解决方案:
(Get-Content $filepath) -replace '(\G(?!^)|^(?=:86:.+WONG TONG))(.*?)([1-7]\d{4}(?!\S))', 'INV'
参见regex demo。 详情:
(\G(?!^)|^(?=:86:.+WONG TONG))
- 第 1 组:上一个成功匹配的结尾 (\G(?!^)
) 或 (|
) 字符串(此处为行)开始位置 (^
) 紧跟:86:
,换行字符以外的任何一个或多个字符,尽可能多,然后是WON TONG
string(.*?)
- 第 2 组 (</code>):除换行字符外的任何零个或多个字符尽可能少</li> <li><code>([1-7]\d{4}(?!\S))
- 第 3 组 (</code>):从 <code>1
到7
的数字,然后是字符串末尾或紧随其后的任意四位数字有一个空格。
(Get-Content $filepath)
逐行读取文件,所以任何不匹配的行将原样输出,不受影响。