2013-08-16 15 views
5

Ho sviluppato un'espressione regolare che corrisponde alle specifiche della pagina pstops. (Spazio bianco Regex non significativo)Con gruppi nidificati denominati in un'espressione regolare, è possibile navigare nella gerarchia?

^(?:(?<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)" 

Come puoi vedere, ci sono sottogruppi nidificati. A pagespec non è necessario specificare rotation, ad esempio. Vorrei essere in grado di fare qualcosa per l'effetto di questo:

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

ma naturalmente Captures ha alcuna proprietà Groups. C'è un modo per accedere ai sottogruppi nella gerarchia in questo modo?

EDIT: Ecco un esempio più minmal (spazio bianco significativa questa volta):

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

confrontati con questa stringa:

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

produce una sola partita. All'interno di questa corrispondenza,

  • Groups("paragraph") ha una cattura corrispondente all'intera stringa.
  • Groups("sentence") ha tre catture.
  • Groups("child") ha due acquisizioni, boy e girl.
  • Groups("parent") ha una cattura, mother.

Ma non c'è nulla che mi dice che il singolo di acquisizione per parent si trova all'interno della seconda acquisizione per sentence, a meno che non mi metto guardando Index e Length per ogni cattura.

EDIT: Ecco la risposta finale:

^(?:(?<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>) 
)+ 

Questo spinge un NULL sul pagespec pila tra ogni page, in modo che possono essere correlati con page; e uno NULL su ciascuno degli altri stack con nome tra ciascuno pagespec. Gee, l'analisi è difficile ...

+1

Suppongo che sarebbe utile per l'utilità della domanda se si riducesse a un esempio minimo. Qualcosa come la corrispondenza di 'xy @ z' con' (? :(? (? :(? [az]) | -) + | @) + 'probabilmente farebbe (come in, come faccio a sapere se' Gruppi ("sub"). Captures (1) 'appartiene a' Groups ("part"). Cattura (0) 'o' (1) '). Ma grande domanda, sarei interessato anche a una soluzione :). –

risposta

2

Non credo sia possibile. Per quanto ne so, i diversi gruppi non hanno alcuna relazione l'uno con l'altro riguardo al modo in cui sono annidati nello schema. Inoltre, una tale gerarchia non avrebbe nemmeno senso, perché i nomi di gruppo possono essere riutilizzati in .NET:

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

Credo che sarebbe stato in qualche modo possibile rappresentare questo un albero gerarchico pure, ma questo sarebbe sconfiggere il scopo degli stack, .NET mantiene le acquisizioni. Forse dovrei chiarire che: .NET non elenca semplicemente tutte le acquisizioni di un gruppo - le inserisce su una pila da cui possono essere nuovamente copiate con (?<-sub>) per esempio. Ora, come lo tratteresti, se un'istanza di un gruppo in seguito apre qualcosa dalla pila che è stata abbinata prima?Penso che diventerebbe poco intuitivo se non impossibile da risolvere per il caso generale.

Quello che in realtà si desidera è raggruppare le tue acquisizioni pagespecs in base alla loro corrispondenza con una singola "istanza" di pages. Si può fare questo il motivo che impedisce la soluzione, si desidera avere: è possibile riutilizzare i gruppi:

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

Ora, alla fine di ogni page si preme una stringa vuota al catasta pagespecs. Poiché una "istanza" normale di pagespecs conterrà sempre almeno un carattere, si sa che eventuali acquisizioni vuote devono provenire da quell'uso separato di pagespecs. Quindi ora puoi dividere l'elemento Captures("pagespecs") con gli elementi stringa vuota e quindi associarli in sequenza con gli elementi in Captures("pages").

+0

Questo è molto interessante. Lo proverò. –

+0

Si noti che un pagepec non deve avere una rotazione. Potrei avere una pagina, cinque pagine e una sola rotazione. Come associo quella rotazione con il pagepec corretto? –

+0

OK, la rotazione era un cattivo esempio: sembra che sia NULL quando non è presente. Ma xoff/xunit/yoff/yunit sono in un gruppo di cattura senza nome che è totalmente opzionale. Omettere che distrugge l'associazione. –

Problemi correlati