解析文件夹中的脚本文件并在Powershell + RegEx中标记多行字符串

时间:2013-09-13 16:02:29

标签: regex powershell powershell-v2.0 tokenize multiline

另一个PowerShell + RegEx进退两难的问题。 尝试解析包含脚本文件的文件夹/目录。找到包含变量设置的脚本,并输出脚本文件名以及分配给变量的值。

我看到的规则是:

  • 所需步骤始终以MVL开头,可能是也可能不是 前面有一个或多个空格。
  • 步骤以冒号(;)结束。
  • 指定的值以',
  • 结束
  • 需要为脚本中的所有MVL步骤显示变量值。

我需要捕获的是脚本文件的名称,以及变量SRCFILESERVERTARGETFILE的值。

我正在寻找的数据是这样的:

MVL       SRCFILE='\PATH\FOLDER\FILENAME.TXT   ',SERVER='SERVERNAME             ',
      TARGETFILE='TARGET.TXT   ',PARM1=O,PARM2=N,PARM3=N,PARM4=Y,PARM5=N,PARM6=' ',
      PARM7=N,PARM8='NONE  ',PARM8='                              ',
      PARM9=00;
Other lines I don't care about

Could be blank lines
* Comment lines will begin with asterisk, need to skip
MVL       SRCFILE='\PATH\FOLDER2\FILENAME'&1'.TXT   ',
          SERVER='SERVERNAME2             ',
      TARGETFILE='TARGET2.TXT   ',PARM1=O,PARM2=N,PARM3=N,PARM4=Y,PARM5=N,PARM6=' ',
      PARM7=N,PARM8='NONE  ',PARM8='                              ',
      PARM9=00;

我从RegEx模式开始,但现在完全失去了。我知道这只会从指定的文件中读取数据。

我最新的是这个,但我不能让它在连续的行中查看并捕获所需的值:

Select-String -Pattern "(?:^[\s]*?MVL\s*?SRCFILE=')(.*)(?:\s+?',)(?:.*$)" c:\scripts\Script1.scl

因此,如果样本数据位于Script1.scl,我的输出将如下所示:

   Script1.scl    \PATH\FOLDER\FILENAME.TXT       SERVERNAME    TARGET.TXT
   Script1.scl    \PATH\FOLDER\FILENAME'&1'.TXT   SERVERNAME2   TARGET2.TXT

2 个答案:

答案 0 :(得分:1)

您可以通过两种方式让select-string搜索多个文件:

Select-String -Pattern "..." c:\scripts\*.sc1

Get-ChildItem c:\scripts\*.sc1 -recurse | Select-String -Pattern "..."

现在它搜索多个找到匹配的文件,它将输出一个具有以下属性的MatchInfo对象:

   TypeName: Microsoft.PowerShell.Commands.MatchInfo

Name         MemberType Definition
----         ---------- ----------
Equals       Method     bool Equals(System.Object obj)
GetHashCode  Method     int GetHashCode()
GetType      Method     type GetType()
RelativePath Method     string RelativePath(string directory)
ToString     Method     string ToString(), string ToString(string directory)
Context      Property   Microsoft.PowerShell.Commands.MatchInfoContext Context {get;set;}
Filename     Property   string Filename {get;}
IgnoreCase   Property   bool IgnoreCase {get;set;}
Line         Property   string Line {get;set;}
LineNumber   Property   int LineNumber {get;set;}
Matches      Property   System.Text.RegularExpressions.Match[] Matches {get;set;}
Path         Property   string Path {get;set;}
Pattern      Property   string Pattern {get;set;}

您可以像这样提取文件名和正则表达式捕获组:

Select-String -Pattern "..." c:\scripts\*.sc1 | Select Filename,
    @{n='ServerName';e={$_.matches.groups[1].Value}}

答案 1 :(得分:0)

这是最终的脚本:

## Folders to check
$TargetFolder1 = “C:\scripts”
$path = $TargetFolder1 + "\*.scl"

$regex = "(?:^[\s]*?MVL\s*?SRCFILE=')"

$scriptFiles=Select-String -Path $path -Pattern $regex | ForEach-Object {$_}

$varObjs = @()

foreach($file in $scriptFiles)
{
    $currentFile = [io.file]::readalltext($file.Path) #-replace "[\r\n]", " "
    $regex = "(?smi)(?:^[\s]*?MVL\s*?SRCFILE=')([^']+)\s*?'\s*?,\r?\n?(?:\s*?SERVER='([^']+)\s*?'\s*?,\r?\n?)?(?:\s*?TARGETFILE='([^']+)\s*?'\s*?,)?"  

    $b = select-string -InputObject $currentFile -AllMatches -Pattern $regex 


    for($i = 0; $i -le $b.Matches.Count-1; $i++)
    {
         $varObj = New-Object System.Object
         $varObj | Add-Member -MemberType NoteProperty -Name ScriptName -Value $file.Path 
         $varObj | Add-Member -MemberType NoteProperty -Name SrcFile -Value $b.Matches[$i].Groups[1].value 
         $varObj | Add-Member -MemberType NoteProperty -Name Server -Value $b.Matches[$i].Groups[2].value
         $varObj | Add-Member -MemberType NoteProperty -Name TargetFile -Value $b.Matches[$i].Groups[3].value

        $varObjs += $varObj
    }

}

$varObjs | Export-Csv -Delimiter "`t" -path c:\Test\Results.txt

exit
相关问题