2013-02-12 105 views
1

我使用Windows 2003 Server x86,Powershell 1.0,并有以下突破性问题。当我试图下面执行脚本,我得到一个错误:PowerShell:如何分配结果,从foreach返回到变量

Error "=" operator: System error. (Fehler beim "="-Operator: Systemfehler.) 
+ $data = <<<< Get-Content $log | % { 

下面是这个脚本:

$log = "C:\log file.txt" 
$linePrefix = "PROCESS THIS LINE" 
$trimStart = 25 #chars to ignore in the beginning 
$started = 0 

$data = Get-Content $log | % { 
    if ($_.length -ge $trimstart) { 
     $linedata = $_.substring($trimstart); 
     $timesline = $linedata.startswith($lineprefix); 
     if ($started -eq 0 -and $timesline) { 
      $started = 1; 
     } 
     if ($started) { 
      if ($timesline) { 
       $line = $linedata.substring($lineprefix.length).trimstart(); 
       if ($line.contains(": ")) { 
        write-output $line 
       } 
      } else { 
       break; 
      } 
     } 
    } 
} 

不过,如果我没有$data =分配执行它,它完美的作品和返回我的预期值。我也试过以下语句

$data = (...) 
$data = $(...) 

并用表达式声明函数但没有成功。

请给我一个提示,为什么它会发生?

更新:我已经试过分配新建分配FY迹象之前和之后删除空格,得到了类似的错误,但现在PowerShell的不喜欢$data=G

Error "=" operator: System error (Fehler beim "="-Operator: Systemfehler.) 
At C:\kosmo\scripts\ps\test.ps1:60 Symbol:7 
+ $data=G <<<< et-Content $log | % { 
+0

你有没有尝试过在一行中执行它? – 2013-02-12 15:53:04

+0

yeap。我为它准备了一行代码:'$ data = Get-Content $ log | %{if($ _。length -ge $ trimstart){$ linedata = $ _。substring($ trimstart); $ timesline = $ linedata.startswith($ lineprefix);如果($开始-eq 0 - 和$ timesline){$开始= 1; }; ($ start){if($ timesline){$ line = $ linedata.substring($ lineprefix.length).trimstart(); if($ line.contains(“:”)){write-output $ line}} else {break; }}}}'。仍然没有 – kosmo 2013-02-12 15:54:55

+0

试过$ data =&{...}? – mjolinor 2013-02-12 15:55:48

回答

0

非常感谢您的提示!可惜,但没有任何建议确实解决了我的问题。 最有用的是从latkin暗示关于打破行为。一些reading后,我发现,在的foreach-Object cmdlet,后者是由别名%,打破或continue语句停止整个脚本只before getting result

function getFilteredResult { 

    1..50 | % { 
     if ($_ -le 20) { 
      if (($_ % 2) -eq 0) { 
       write-output $_; 
      } 
     } else { 
      break; #terminates whole script, you don't even get "after got result" 
      #continue; #save result as break 
     } 
    } 
} 

Write-Host "before getting result" 

$result = getFilteredResult 

$result | % {$i=0}{ ++$i; Write-Host "$i) $_" } 

Write-Host "after got result" 

输出显示。从那里我得出结论:在Powershell 1.0中无法做到我想要的东西!所以我发现a way在我的旧的2003年服务器上安装Powershell 2.0(tip如何卸载Powershell 1.0之前;顺便说一下,我的Windows更新名称为KB926140-v5)。

好吧,错误已经消失。但我仍然没有我想要的结果?!在我的旅程结束时,我觉得很useful post和已经写在下面

function getFilteredResult { 
    Try { 
     1..50 | % { 
      if ($_ -le 20) { 
       if (($_ % 2) -eq 0) { 
        write-output $_; 
       } 
      } else { 
       #break; #terminates whole script, you don't even get "after got result" 
       #continue; #terminates whole script, you don't even get "after got result" 
       throw "terminated pipeline!" 
      } 
     } 
    } Catch { 
     #ignore terminated pipeline exception 
    } 
} 

Write-Host "before getting result" 

$result = getFilteredResult 

$result | % {$i=0}{ ++$i; Write-Host "$i) $_" } 

Write-Host "after got result" 

脚本,并得到了一个答案:

before getting result 
1) 2 
2) 4 
3) 6 
4) 8 
5) 10 
6) 12 
7) 14 
8) 16 
9) 18 
10) 20 
after got result 

解释 如果我使用foreach声明,我可以用突破与估计的行为,但我正在处理大型日志文件和foreach语句将整个文件读入内存,而ForEach-Object cmdlet进程逐行处理。我不确定Get-Content cmdlet,也许它也读取整个文件以返回它,但我写下了自己的cmdlet Get-Content-Reversed从文件末尾读取行,这就是为什么我很漂亮确定它不是

0

我已经转换你的代码的函数那会返回一个String对象。所以,你可以如下运行:

$data = Parse-LogFile 

您需要先导入功能到你的shell,你可以通过简单地复制和粘贴

Function Parse-LogFile 
{ 
    $log = gc "C:\log file.txt" 
    $linePrefix = "PROCESS THIS LINE" 
    $trimStart = 25 #chars to ignore in the beginning 
    $started = 0 
    $ReturnText = New-Object System.Text.StringBuilder 
    foreach ($line in $log) 
    { 
     if ($_.length -ge $trimstart) 
     { 
     $linedata = $_.substring($trimstart); 
     $timesline = $linedata.startswith($lineprefix); 

     if ($started -eq 0 -and $timesline) 
     { 
      $started = 1; 
     } 

     if ($started) 
     { 
      if ($timesline) 
      { 
       $line = $linedata.substring($lineprefix.length).trimstart(); 
       if ($line.contains(": ")) 
       { 
        $ReturnText.Append($line) 
        $ReturnText.AppendLine() 
       } 
      } 
      else 
      { 
       break; 
      } 
     } 
     } 
    } 

    Retrun $ReturnText.ToString() 
} 
+0

谢谢,但我仍然需要它作为一束线,而不是一个单一的字符串。我想将这些数据作为参数提供给几个统计函数 – kosmo 2013-02-12 16:40:47

+0

字符串对象是一堆行,您可以像遍历$ log变量一样遍历它,就像我们也是一个字符串对象一样。 – 2013-02-12 17:01:36

+0

谢谢,但我想避免使用'foreach'语句,它在开始处理之前迭代整个集合;这就是为什么我需要使用'ForEach-Object'-cmdlet – kosmo 2013-02-13 10:41:17

0

虽然我不能重现。你的问题在我的机器上,我认为这个问题可能与你在任务中使用管道内的break有关。作为第一个测试,如果您删除了break,它会改变什么吗?

假设这确实是问题,您可以稍微重构以避免直接进行分配。相反,你可以在循环内建立自己的$data变量。

$log = ".\logfile.log" 
$linePrefix = "PROCESS THIS LINE" 
$trimStart = 25 #chars to ignore in the beginning 
$started = 0 
$data = @() # initialize blank data array 

Get-Content $log | % { 
    if ($_.length -ge $trimstart) { 
     $linedata = $_.substring($trimstart); 
     $timesline = $linedata.startswith($lineprefix); 
     if ($started -eq 0 -and $timesline) { 
      $started = 1; 
     } 
     if ($started) { 
      if ($timesline) { 
       $line = $linedata.substring($lineprefix.length).trimstart(); 
       if ($line.contains(": ")) { 
        # add to your result here 
        $data += $line 
       } 
      } else { 
       break; 
      } 
     } 
    } 
} 

现在$data包含你想要的。这可能不是性能最佳的代码,具体取决于您期望得到多少结果,但它可能会为您提供一个开始。

+0

感谢您提供有关休息的有用提示!我从中找到了一些有用的信息,在我的答案中详细说明 – kosmo 2013-02-13 10:33:35