我的文本文件包含 2 个由“+”号分隔的数字。试图弄清楚如何用等值的货币替换它们。
示例字符串:
20+2 would be converted to $0.20+$0.02 USD
1379+121 would be> $13.79+$1.21 USD
400+20 would be $4.00+$0.20 USD
等等。
我尝试过使用几个角度,但它们不起作用或提供奇怪的结果。 我试图通过尝试找到我认为会出现的所有模式来做到这一点。
.\Replace-FileString.ps1 "100+10" '$1.00+$0.10' $path1\*.txt -Overwrite
.\Replace-FileString.ps1 "1000+100" '$10.00+$1.00' $path1\*.txt -Overwrite
.\Replace-FileString.ps1 "300+30" '$3.00+$0.30' $path1\*.txt -Overwrite
.\Replace-FileString.ps1 "400+20" '$4.00+$0.20' $path1\*.txt -Overwrite
或者这个不起作用。
Select-String -Path .\*txt -Pattern '[0-9][0-9]?[0-9]?[0-9]?[0-9]?\+[0-9][0-9]?[0-9]?[0-9]?[0-9]?' | ForEach-Object {$_ -replace ", ", $"} {$_ -replace "+", "+$"}
请您参考如下方法:
I tried to do it here by attempting to find by all patterns I think would come up
不要尝试这个 - 我们是人类,我们不会考虑所有边缘情况,即使我们考虑了,我们需要编写(或生成)的代码量也将是荒谬的。
我们在这里需要一个更通用的解决方案,正则表达式可能确实对此有所帮助。
您描述的模式可以表示为三个不同的部分:
- 1 个或多个连续数字
- 1 个加号 (
+
) - 1 个或多个连续数字
考虑到这一点,让我们开始简化要使用的正则表达式模式:
\b\d+\+\d+\b
或者,写出解释:
\b # a word boundary
\d+ # 1 or more digits
\+ # 1 literal plus sign
\d+ # 1 or more digits
\b # a word boundary
现在,为了将美分的绝对值转换为美元,我们需要捕获 +
两边的数字,所以让我们添加捕获组:
\b(\d+)\+(\d+)\b
现在,为了对捕获的组做任何有趣的事情,我们可以利用 Regex.Replace()
method - 它可以将脚本 block 作为其替换参数:
$InputString = '1000+10'
$RegexPattern = '\b(\d+)\+(\d+)\b'
$Substitution = {
param($Match)
$Results = foreach($Amount in $Match.Groups[1,2].Value){
$Dollars = [Math]::Floor(($Amount / 100))
$Cents = $Amount % 100
'${0:0}.{1:00}' -f $Dollars,$Cents
}
return $Results -join '+'
}
在上面的脚本 block 中,我们期望两个捕获组 ($Match.Groups[1,2]
),计算美元和美分的数量,然后最后使用 - f
字符串格式运算符,以确保美分值始终为两位数宽。
要进行替换,请调用 Replace()
方法:
[regex]::Replace($InputString,$RegexPattern,$Substitution)
好了!
应用到一堆文件很简单:
$RegexPattern = '\b(\d+)\+(\d+)\b'
$Substitution = {
param($Match)
$Results = foreach($Amount in $Match.Groups[1,2].Value){
$Dollars = [Math]::Floor(($Amount / 100))
$Cents = $Amount % 100
'${0:0}.{1:00}' -f $Dollars,$Cents
}
return $Results -join '+'
}
foreach($file in Get-ChildItem $path *.txt){
$Lines = Get-Content $file.FullName
$Lines |ForEach-Object {
[regex]::Replace($_, $RegexPattern, $Substitution)
} |Set-Content $file.FullName
}