Select-String有时会导致" System.Object []"

时间:2014-08-21 21:12:17

标签: powershell csv

我正在编写一个结合了两个文本文件部分的脚本。这些文件不是太大(每个约2000行)。 我看到select-string的奇怪输出,我认为不应该存在。 这是我的两个文件的样本:

CC.csv - 2026行

LS126L47L6/1L2#519,07448,1,B
LS126L47L6/1R1-1#503,07449,1,B
LS126L47L6/1L3#536,07450,1,B
LS126L47L6/2R1#515,07451,1,B
LS126L47L6/10#525,07452,1,B
LS126L47L6/1L4#538,07453,1,B

GI.txt - 1995行

07445,B,SH,1
07446,B,SH,1
07448,B,SH,1
07449,B,SH,1
07450,B,SH,1
07451,B,SH,1
07452,B,SH,1
07453,B,SH,1
07454,B,SH,1

这是输出文件的示例:

输出myfile.csv

 LS126L47L6/3R1#516,07446,1,B
 LS126L47L6/1L2#519,07448,1,B
 LS126L47L6/1R1-1#503,07449,1,B
 System.Object[],B
 LS126L47L6/2R1#515,07451,1,B

这是我正在使用的脚本:

sc ./myfile.csv "col1,col2,col3,col4"

$mn = gc cc.csv | select -skip 1 |  % {$_.tostring().split(",")[1]}
$mn | % {
        $a = (gc cc.csv | sls $_ ).tostring() -replace ",[a-z]$", ""
        if (gc GI.txt | sls $_ | select -first 1)
            {$b = (gc GI.txt | sls $_ | select -first 1).tostring().split(",")[1]}
        else {$b = "NULL"
                write-host "$_ is not present in GI file"}
        $c = $a + ',' + $b
        ac ./myfile.csv -value $c
        }

$ a变量是我有时将返回的字符串看作 System.Object [] 的地方 有什么想法吗?此外,此脚本需要相当长的时间才能完成。关于如何加速它的任何提示?

编辑:我应该补充一点,我从cc.csv文件中取一行,保存在一个新的文本文件中,然后通过分配$ a在控制台中运行脚本。我无法让它返回" system.object []"。

编辑2:按照下面的建议并尝试了几件我已经注意到的事情,如果我跑了

$mn | %{(gc cc.csv | sls $_).tostring()}

我得到System.Object []。
但如果我跑

$mn | %{(gc cc.csv | sls $_)} | %{$_.tostring()}

很好。去图。

1 个答案:

答案 0 :(得分:0)

问题是由匹配多重性的变化引起的。如果有多个匹配元素,则返回Object[]数组(MatchInfo元素);单个匹配元素会生成一个MatchInfo对象(数组中);如果没有匹配项,则返回null

当针对" cc.csv"执行时,请考虑这些结果。提供的测试数据:

# matches many
(gc cc.csv | Select-String "LS" ).GetType().Name # => Object[]
# matches one
(gc cc.csv | Select-String "538").GetType().Name # => MatchInfo
# matches none
(gc cc.csv | Select-String "FAIL")               # => null

在Object []上调用ToString的结果是" System.Object []"而当直接在MatchInfo对象上调用时,结果是匹配值的更有用的串联。

可以使用selected | Select -First 1修复直接问题,这将导致前两种情况返回MatchInfo。 Select-String仍会搜索整个输入 - 只会丢弃额外的结果。

然而,它似乎回顾了" cc.csv" (使用Select-String)可以完全消除,因为$_最初来自哪里。这是一个小的[未经测试的]改编,它可能是什么样的:

gc cc.csv | Select -Skip 1 | %{
    $num = $_.Split(",")[1]
    $a = $_ -Replace ",[a-z]$", ""
    # This is still O(m*n) and could be improved with a hash/set probe.
    $gc_match = Select-String $num -Path gi.csv -SimpleMatch | Select -First 1
    if ($gc_match) {
       # Use of "Select -First 1" avoids the initial problem; but 
       # it /may/ be more appropriate for an error to indicate data problems.
       # (Likewise, an error in the original may need further investigation.)
       $b = $gc_match.ToString().Split(",")[1]
    } else {
       $b = "NULL"
       Write-Host "$_ is not present in GI file"
    }
    $c = $a + ',' + $b
    ac ./myfile.csv -Value $c
}