2010-05-18 39 views
1

我有一個文本文件,列出大量Excel電子表格的名稱以及從電子表格鏈接到的文件的名稱。使用PowerShell使用正則表達式匹配重複子系列

在簡化的形式,它看起來像這樣:

"Parent 
File1.xls" 

    Link: ChildFileA.xls 
    Link: ChildFileB.xls 
"ParentFile2.xls" 
"ParentFile3.xls" 
    Blah 
    Link: ChildFileC.xls 
    Link: ChildFileD.xls 
    More Junk 
    Link: ChildFileE.xls 
"Parent 
File4.xls" 
    Link: ChildFileF.xls 

在這個例子中,已經ParentFile1.xls嵌入式鏈接到ChildFileA.xls和ChildFileB.xls,ParentFile2.xls沒有嵌入式鏈接,以及ParentFile3.xls有3個嵌入式鏈接。

我試圖寫在PowerShell中的正則表達式將解析以下形式的文本文件生成輸出:

ParentFile1.xls:ChildFileA.xls,ChildFileB.xls 
ParentFile3.xls:ChildFileC.xls,ChildFileD.xls,ChildFileE.xls 
etc 

的任務是通過該文本文件包含大量的垃圾的事實複雜化在每一行之間,父母可能並不總是有一個孩子。此外,單個文件名可能會通過多行。但是,它並不像聽起來那麼糟糕,因爲父文件名和子文件名總是明確劃分的(父母用引號和孩子用Link的前綴:)。我一直在使用

PowerShell的代碼如下:

$content = [string]::Join([environment]::NewLine, (Get-Content C:\Temp\text.txt)) 
$regex = [regex]'(?im)\s*\"(.*)\r?\n?\s*(.*)\"[\s\S]*?Link: (.*)\r?\n?' 
$regex.Matches($content) | %{$_.Groups[1].Value + $_.Groups[2].Value + ":" + $_.Groups[3].Value} 

使用上面的例子,它輸出:

ParentFile1.xls:ChildFileA.xls 
ParentFile2.xls""ParentFile3.xls:ChildFileC.xls 
ParentFile4.xls:ChildFileF.xls 

有兩個問題。首先,每當處理一個沒有孩子的父母時,就包含「」而不是一個換行符。第二個問題是最重要的,那就是每個家長只能看到一個孩子。我猜我需要以某種方式遞歸地捕獲和顯示每個父代存在的多個子鏈接,但我完全難以理解如何使用正則表達式來實現這一點。

艾米的幫助將不勝感激。該文件包含成千上萬的行,手動處理不是一個選項:)

+0

Eww,什麼格式。實際上有多嚴格?你當前的正則表達式只能處理分成兩行的父文件名,而不是一行,三行或更多;那是問題嗎?此外,垃圾可以包含引號(即我們如何知道何時終止解析單個父代)? 我認爲這可能是一個正則表達式,但可能更容易沒有。正則表達式部分是一個需求還是隻是一個實現想法? – 2010-05-18 10:41:47

+0

到目前爲止,我所採用的數據樣本表明,父文件名只會分成兩行,但理論上它可能會擴展到3.垃圾不會包含引號。正則表達式不是要求,只是一個實現的想法。 – Hinch 2010-05-18 11:06:59

回答

1

個人我只會解決使用正則表達式的一部分。

首先,我會加入這樣的父文件名:

$text = (Get-Content C:\Temp\text.txt) -join "`r`n" 
$text = [regex]::replace($text, '(?im)"Parent[^"]+"', { [regex]::replace($args, '(?m)\s*', '') }) 

然後用手工加工繼續。

$res = @() 
$parent = $null 
switch -regex ($text -split "`n") { 
    '^"Parent' { if ($parent) { $res += $parent } 
       $parent = new-object PsObject -prop @{Name = $_.Trim('"'); [email protected]()} 
    } 
    '^\s*Link:' { $parent.Links += $_ -replace '^\s*Link:\s*', '' } 
} 
if ($parent) { $res += $parent } 

$res | % { 
$n = $_.Name 
$links = $_.Links -join ',' 
write-host "$n`:$links" 
} 
+0

不錯的工作。這就是訣竅。雖然我認爲$ text2實際上應該是$ text。 – Hinch 2010-05-18 11:14:31

+0

是的,舊的變量名稱;) – stej 2010-05-18 11:17:09