2013-02-12 36 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