2013-08-16 24 views
5

我開發了一個匹配pstops頁面規範的正則表達式。 (正則表達式空格不顯着。)在正則表達式中嵌套命名組,可能導航層次結構?

^(?:(?<modulo>\d+):)? 
(?<pages> 
    (?<pagespec> 
    (?<pageno>-?\d+) 
    (?<rotation>[RUL]?)? 
    (?:@(?<scale>\d*(?:\.\d+)))? 
    (?:\(
     (?<xoff>\d*\.?\d+)(?<xunit>in|cm|w|h)? 
     , 
     (?<yoff>\d*\.?\d+)(?<yunit>in|cm|w|h)? 
    \))? 
    \+?)+,? 
)+$ 

'Sample string: 
'"4:[email protected](21cm,0)[email protected](21cm,14.85cm),1L(21cm,0)[email protected](21cm,14.85cm)" 

正如你所看到的,有嵌套命名的子組。例如,A pagespec不需要指定rotation。我希望能夠做一些這樣的效果:

If match.Groups("pages").Captures(0).Groups("pagespecs").Captures(1).Groups("rotation").Value > "" 

當然Captures的,但沒有Groups財產。有沒有辦法以這種方式訪問​​層次結構中的子組?

編輯:這裏是一個更minmal示例(白空間顯著此時間):

(?<paragraph>(?:(?<sentence>The (?<child>boy|girl) is hungry\.|The (?<parent>mother|father) is angry\.)\s*)+) 

匹配針對此字符串:

The boy is hungry. The mother is angry. The girl is hungry. 

產生一個匹配。在該匹配中,

  • Groups("paragraph")有一個匹配整個字符串的捕獲。
  • Groups("sentence")有三個捕獲。
  • Groups("child")有兩個捕獲,boygirl
  • Groups("parent")有一個捕獲,mother

但並沒有什麼,告訴我,對於parent單捕捉位於第二捕獲內的sentence,除非我開始看IndexLength每次捕捉。

編輯:這裏是最終的答案:

^(?:(?<modulo>\d+):)? 
(?<pages> 
    (?<pagespec> 
    (?<pageno>-?\d+) 
    (?<rotation>[RUL]?) 
    (?:@(?<scale>\d*(?:\.\d+)))? 
    (?:\(
     (?<xoff>\d*\.?\d+)(?<xunit>in|cm|w|h)? 
     , 
     (?<yoff>\d*\.?\d+)(?<yunit>in|cm|w|h)? 
    \))? 
    (?<pageno>)(?<rotation>)(?<scale>)(?<xoff>)(?<xunit>)(?<yoff>)(?<yunit>) 
    \+?)+,? 
(?<pagespec>) 
)+ 

這推動一個NULL到每個page之間的pagespec棧,因此它們可與可page相關;和一個NULL到每個pagespec之間的其他指定堆棧上。嘖嘖,解析很難...

+1

我想這將有助於問題的用處,如果您將此減少到最小范例。有些東西就像'xy @ z'與'(?:(?:????????????????????????????????????????????[az]) - )+ 「sub」)。捕獲(1)'屬於'Groups(「part」)。捕獲(0)'或'(1)')。但是很好的問題,我也會對解決方案感興趣:)。 –

回答

2

我不認爲這是可能的。據我所知,不同的團體在模式中如何嵌套,彼此之間沒有任何關係。此外,這樣的層級甚至沒有任何意義,因爲集團的名稱可以在.NET中被重用:

(?<group> 
    (?<sub>.) 
)+ 
(?<sub>.) 

我想這會在某種程度上能夠代表這個層次樹爲好,但這會破壞堆棧的目的,.NET維護捕獲。也許我應該澄清一點:.NET不會簡單地列出一個組的所有捕獲 - 它將它們推到一個堆棧上,從中可以再次彈出,例如(?<-sub>)。現在,如果一個組的實例稍後從堆棧中彈出一些與之前相匹配的方式,那麼你會如何處理呢?如果不是一般情況下不可能解決的話,我認爲這會變得非常不直觀。

你真正想要的是將你的pagespecs捕獲按照它們對應於pages的單個「實例」的方式分組。你可以通過這個原因,以防止該解決方案做到這一點,你想有:你可以重用組:

^(?:(?<modulo>\d+):)? 
(?<pages> 
    (?<pagespecs> 
    # here goes your actual pagespec pattern 
    [+]?)+ 
    (?<pagespecs>) 
    ,? 
)+$ 

現在每page結束時,您到pagespecs壓棧一個空字符串。由於pagespecs的正常「實例」將始終包含至少一個字符,因此您知道任何空的捕獲必須來自單獨使用pagespecs。因此,您現在可以通過空字符串元素將您拆分爲Captures("pagespecs"),然後將它們按順序與Captures("pages")中的元素相關聯。

+0

這非常有趣。我會試試看。 –

+0

請注意,pagespec不必旋轉。我可能只有一頁,五頁的規格,只有一個輪播。我如何將這一輪轉換與正確的pagespec相關聯? –

+0

好吧,旋轉是一個不好的例子 - 它似乎沒有出現時變成NULL。但是xoff/xunit/yoff/yunit在一個完全可選的未命名捕獲組中。省略破壞聯繫。 –