Powershell解析文本文件的一部分并保存为CSV

时间:2013-03-13 02:22:14

标签: parsing powershell text csv

所有,我对powershell很新,我希望有人可以让我继续我认为简单的脚本。

我需要解析一个文本文件,从中捕获某些行,然后将这些行保存为csv文件。

例如,每个警报都在其自己的文本文件中。每个文件都与此类似:

- 文件开头---

姓名约翰史密斯 部门会计 代码bas-2349,cav-3928,deg-3942
耶-2830,TEL-3890
网址hxxp://blah.com
hxxp://foo.com,hxxp://foo2.com
一些我不关心的文字 更多文字我不在乎 评论
 ---------
“这是一条多线路 我需要评论 捕获“ 一些我不关心的文字 更多文字我不在乎 日期3/12/2013

---文件结束---

对于每个文本文件,如果我只想将名称,代码和URL写入CSV文件。有人可以帮我解决这个问题吗?

我更像是一个PERL家伙所以我知道我可以编写一个正则表达式来捕获以Name开头的单行。但是,当我遇到“代码”行时,我完全迷失了它可能是一行,或者可能是X行,直到我遇到Urls字段。

非常感谢任何帮助!

5 个答案:

答案 0 :(得分:0)

如果文件不是太大而无法在内存中处理,那么简单的方法是将其作为字符串数组读取。 (太大的意思是你的系统。任何亚GB都应该没有太多的工作。)

读完文件后,设置一个head和tail计数器指向元素零。逐行向前移动尾指针,直到找到日期行。您可以使用regexp匹配数据。现在您知道单个记录的开始和结束。对于下一条记录,将head counter设置为tail + 1,tail to tail + 2并再次开始扫描行。泡沫,冲洗,重复直到阵列结束。

匹配记录时,可以使用正则表达式提取名称。代码和网址有点棘手。将代码行与正则表达式匹配。除非它们与代码模式不匹配,否则提取它和所有下一行。同样适用于Urls数据。如果文件始终在作为以前的Urls和代码的数据的行上具有空格填充,则可以使用匹配空白计数和正则表达式来获取数据行。

答案 1 :(得分:0)

也许这就行了:

foreach ($Line in gc file.txt) {
    switch -regex ($Line) {
        '^(Name|Dept|Codes|Urls)' {
            $Capture = $true
            break
        }
        '^[A-Za-z0-9_-]+' {
            $Capture = $false
            break
        }
    }
    if ($Capture) {
        $Line
    }
}

如果您希望将最终结果作为CSV文件,则可以使用Export-Csv cmdlet。

答案 2 :(得分:0)

如果所有文件具有相同的结构,您可以执行以下操作:

$srcdir  = "C:\Test"
$outfile = "$srcdir\out.csv"

$re = '^Name (.*(?:\r\n .*)*)\r\n' +
      'Dept .*(?:\r\n .*)*\r\n' +
      'Codes (.*(?:\r\n .*)*)\r\n' +
      'Urls (.*(?:\r\n .*)*)' +
      '[\s\S]*$'

Get-ChildItem $srcdir -Filter *.txt | % {
  [io.file]::ReadAllText($_.FullName)
} | Select-String $re | % {
  $f = $_.Matches | % { $_.Groups } | ? { $_.Index -gt 0 }
  New-Object -TypeName PSObject -Prop @{
      'Name'  = $f[0].Value;
      'Codes' = $f[1].Value;
      'Urls'  = $f[2].Value;
    }
} | Export-Csv $outfile -NoTypeInformation

答案 3 :(得分:0)

文本解析通常意味着正则表达式。使用正则表达式,有时你需要锚点来知道何时停止匹配,这可以让你关心文本,否则你不会。如果您可以指定第一行“我不关心某些文字”,您可以使用它来“锚定”您的网址匹配,以便您知道何时停止匹配。

$regex = @'
(?ms)Name (.+)?
 Dept .+?
 Codes (.+)?
 Urls (.+)?
 Some text I dont care about.+
 Comments
 ---------
 (.+)?
 Some text I dont care about 
'@

$file = 'c:\somedir\somefile.txt'
[IO.File]::ReadAllText($file) -match $regex
if ([IO.File]::ReadAllText($file) -match $regex)
  {
   $Name = $matches[1]
   $Codes = $matches[2] -replace '\s+',','
   $Urls = $matches[3] -replace '\s+',','
   $comment = $matches[4] -replace '\s+',' '
  }

$Name
$Codes
$Urls
$comment

答案 4 :(得分:0)

根据c:\temp\file.txt包含的事实:

Name John Smith
Dept Accounting
Codes bas-2349,cav-3928,deg-3942
      iye-2830,tel-3890
Urls hxxp://blah.com
     hxxp://foo.com
     hxxp://foo2.com
Some text I dont care about
More text i dont care about
.
.
Date 3/12/2013

你可以使用这样的正则表达式:

$a = Get-Content C:\temp\file.txt
$b = [regex]::match($a, "^.*Codes (.*)Urls (.*)Some.*$", "Multiline")
$codes = $b.groups[1].value -replace '[ ]{2,}',','
$urls = $b.groups[2].value -replace '[ ]{2,}',','