PowerShell foreach循环用+=追加数组时已存数据被同步修改问题
问题原因
PSObject.Copy()是浅拷贝方法,你当前代码的核心问题是在while循环外只做了一次对象拷贝生成$line2,循环过程中反复修改这同一个对象的属性,再重复把它的引用加入数组。
PowerShell的数组存储引用类型对象时,存的是对象的内存指针而非对象本身的副本,你数组里所有拆分出来的条目本质上都指向同一个$line2实例,所以最后一次对Document Number的修改,会覆盖之前所有条目的值,才会出现所有行的单据号都变成最后一个值的现象。
另外你的代码还有三个隐藏bug:
- 后缀匹配的正则
^*[A-Z]$存在语法错误,量词*前没有指定匹配规则,运行时会抛出正则解析异常 - 单据号递增的计数器
$counter没有初始化初始值,首次运行时会取到空值导致计算错误 - 提前把原始行的
Qty修改为1,会影响后续循环的计数逻辑
修复方法
把对象拷贝逻辑移到while循环内部,每生成一行就基于原始行创建一个全新的独立对象副本,避免多个数组条目共用同一个对象引用,同时修正上述隐藏bug即可。
修复后的核心逻辑代码如下:
# 导入原始Excel $report = Import-Excel "pathToFile.xlsx" $result = @() foreach($line in $report){ # 数量小于等于1的行直接加入结果 if($line.Qty -le 1){ $result += $line.PSObject.Copy() continue } # 拆分原始单据号 $docPrefix = $line.'Document Number'.Split("-")[0] $docSuffix = $line.'Document Number'.Split("-")[1] $suffixLetter = "" # 提取后缀末尾的字母、数字基数 if($docSuffix -match "[A-Z]$"){ $suffixLetter = $docSuffix.Substring($docSuffix.Length - 1, 1) $baseNumber = [int]$docSuffix.Substring(0, 2) }else{ $baseNumber = [int]$docSuffix } # 初始化计数器 $counter = 0 # 按数量逐行生成新条目 while($counter -lt $line.Qty){ # 每次循环都创建独立的对象副本,禁止复用同一个对象 $newRow = $line.PSObject.Copy() $currentSuffixNum = '{0:d2}' -f ($baseNumber + $counter) $newRow.'Document Number' = "$docPrefix-$currentSuffixNum$suffixLetter" $newRow.Qty = 1 $result += $newRow $counter++ } } # 导出处理完成的结果 $result | Export-Excel "newFile.xlsx"
注:你之前写的把
$report全量拷贝到$report2的步骤是多余的,可以直接删除,只要保证加入结果数组的每个元素都是独立拷贝的新实例就不会出现引用同步问题。
内容的提问来源于stack exchange,提问作者Milan Patel
相关产品推荐
相关产品推荐

