PowerShell管道中$_($PSItem)作用域冲突问题求助
解决PowerShell中ForEach-Object作用域与类型转换方法的
$_冲突问题 这个问题的核心是作用域混淆:在ForEach-Object(简写为%)的脚本块里,$_代表当前遍历的$cont元素(也就是整行字符串),而你调用$var1[1].ToInt16($_)时,方法里的$_并没有自动切换为$var1[1]本身——实际上,字符串的ToInt16方法需要的是一个IFormatProvider类型的参数,你传了外层的$_(整行字符串),自然会触发类型转换错误。
几种可行的解决方案:
1. 使用PowerShell原生类型转换语法(最推荐)
PowerShell支持直接用类型强制转换,这种写法更简洁,也完全避免了作用域混淆的问题:
$cont = @( "2019-01-01 00:00:00;0;1;224.94999999999999;13.710000000000001;7.9226000000000005E-2", "2019-01-01 00:00:00;0;2;-5.9999999999999998E-2;13.630000000000001;6.0484000000000003E-2" ) $cont | % { $lig = $_ # 生产环境行 # $lig = $cont[0].split(';') # 测试用行 $var1 = $lig.split(';') try { [datetime]$var1[0] [int16]$var1[1] [int16]$var1[2] [float]$var1[3] [float]$var1[4] [float]$var1[5] } catch { write-host "Erreur dans la ligne $lig" } }
2. 使用[Convert]类的静态方法
静态方法的参数更明确,你可以直接传入要转换的字符串,彻底避开作用域冲突:
$cont = @( "2019-01-01 00:00:00;0;1;224.94999999999999;13.710000000000001;7.9226000000000005E-2", "2019-01-01 00:00:00;0;2;-5.9999999999999998E-2;13.630000000000001;6.0484000000000003E-2" ) $cont | % { $lig = $_ # 生产环境行 # $lig = $cont[0].split(';') # 测试用行 $var1 = $lig.split(';') try { [Convert]::ToDateTime($var1[0]) [Convert]::ToInt16($var1[1]) [Convert]::ToInt16($var1[2]) [Convert]::ToSingle($var1[3]) [Convert]::ToSingle($var1[4]) [Convert]::ToSingle($var1[5]) } catch { write-host "Erreur dans la ligne $lig" } }
3. 给目标变量单独命名,明确作用域
如果一定要用字符串实例的ToInt16方法,可以把要转换的字符串赋值给一个局部变量,避免和外层$_冲突:
$cont = @( "2019-01-01 00:00:00;0;1;224.94999999999999;13.710000000000001;7.9226000000000005E-2", "2019-01-01 00:00:00;0;2;-5.9999999999999998E-2;13.630000000000001;6.0484000000000003E-2" ) $cont | % { $lig = $_ # 生产环境行 # $lig = $cont[0].split(';') # 测试用行 $var1 = $lig.split(';') try { $dateStr = $var1[0] $dateStr.ToDateTime($null) # 不需要格式提供器时传$null $intStr1 = $var1[1] $intStr1.ToInt16($null) $intStr2 = $var1[2] $intStr2.ToInt16($null) $floatStr1 = $var1[3] $floatStr1.ToSingle($null) $floatStr2 = $var1[4] $floatStr2.ToSingle($null) $floatStr3 = $var1[5] $floatStr3.ToSingle($null) } catch { write-host "Erreur dans la ligne $lig" } }
为什么原来的写法会出错?
当你在ForEach-Object的脚本块里写$var1[1].ToInt16($_)时,这里的$_仍然指向当前的$cont元素(也就是$lig的原始值,整行字符串),而不是$var1[1]。String.ToInt16()方法的第一个参数是IFormatProvider,你传入一个字符串类型的值,自然会触发"无法转换为System.IFormatProvider"的错误。
内容的提问来源于stack exchange,提问作者Info VSA
相关产品推荐
相关产品推荐

