1

我正在使用 Windows 2003 Server x86、Powershell 1.0 并遇到以下令人头疼的问题。当我尝试执行下面的脚本时,出现错误:

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 = $(...)

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

你能告诉我为什么会发生吗?

更新:我尝试在分配符号之前和之后删除空格并得到类似的错误,但现在 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 | % {
4

3 回答 3

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()
}
于 2013-02-12T16:15:48.057 回答
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包含你想要的。这可能不是性能最好的代码,具体取决于您期望有多少结果,但它可能会给您一个开始。

于 2013-02-12T18:24:57.310 回答
0

感谢大家的提示!可惜,但没有任何建议确实解决了我的问题。最有帮助的是 latkin 关于中断行为的提示。经过一番阅读,我发现,在 Foreach-Object cmdlet(由 % 别名)中,break 或 continue 语句会停止整个脚本

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"

输出仅显示before getting result. 从那里我得出的结论是,在 Powershell 1.0 中没有办法做我想做的事!所以我找到了一种在我的旧 2003 服务器上安装 Powershell 2.0 的方法(提示如何卸载 Powershell 1.0;顺便说一句,我的 Windows 更新名为 KB926140-v5)。

好的,错误消失了。但是我还是没有想要的结果?!在我的旅程结束时,我发现了非常有用的帖子并在下面编写了脚本

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了语句,我可以使用 break 来估计行为,但是我正在处理大型日志文件,foreach-statement 将整个文件读入内存,而 ForEach-Object cmdlet 则逐行处理。我不确定 Get-Content cmdlet,也许它也会读取整个文件以返回它,但我已经写下了我自己的 cmdlet Get-Content-Reversed 从文件末尾读取行,这就是为什么我很漂亮当然不是

于 2013-02-13T10:32:55.730 回答