所有,我对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字段。
非常感谢任何帮助!
答案 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,}',','