2009-05-02 16 views
10

Sto cercando le seguenti parole in .todo file:Quale regex di Perl può corrispondere alle parole di CamelCase?

ZshTabCompletionBackward 
MacTerminalIterm 

ho fatto la seguente espressione regolare

[A-Z]{1}[a-z]*[A-Z]{1}[a-z]* 

Tuttavia, non è sufficiente, dal momento che trova solo il seguente tipo di parole

ZshTab 

In pseudo-codice, io sto cercando di fare la seguente espressione regolare

([A-Z]{1}[a-z]*[A-Z]{1}[a-z]*){1-9} 

Come si può eseguire la regex di cui sopra in Perl?

risposta

21

Penso che si desidera qualcosa di simile, scritto con la bandiera /x per aggiungere commenti e spazi insignificanti:

 
/
    \b  # word boundary so you don't start in the middle of a word 

    (   # open grouping 
     [A-Z]  # initial uppercase 
     [a-z]*  # any number of lowercase letters 
    )   # end grouping 

    {2,} # quantifier: at least 2 instances, unbounded max 

    \b  # word boundary 
/x 

Se si desidera senza la formattazione di fantasia, è sufficiente rimuovere lo spazio bianco e commenti:

 
/\b([A-Z][a-z]*){2,}\b/ 

Come fa notare j_random_hacker, questo è un po 'semplice poiché corrisponderà a una parola che è solo lettere maiuscole consecutive. La sua soluzione, che ho ampliato con /x per mostrare qualche dettaglio, assicura almeno una lettera minuscola:

 
/
    \b   # start at word boundary 
    [A-Z]  # start with upper 
    [a-zA-Z]* # followed by any alpha 

    (?: # non-capturing grouping for alternation precedence 
     [a-z][a-zA-Z]*[A-Z] # next bit is lower, any zero or more, ending with upper 
      |      # or 
     [A-Z][a-zA-Z]*[a-z] # next bit is upper, any zero or more, ending with lower 
    ) 

    [a-zA-Z]* # anything that's left 
    \b   # end at word 
/x 

Se si desidera senza la formattazione di fantasia, basta rimuovere lo spazio bianco e commenti:

 
/\b[A-Z][a-zA-Z]*(?:[a-z][a-zA-Z]*[A-Z]|[A-Z][a-zA-Z]*[a-z])[a-zA-Z]*\b/ 

Spiego tutte queste funzioni in Learning Perl.

+3

Non è una singola parola in maiuscolo (come Perl o Boing) anche una parola CamelCase valida?In tal caso, il quantificatore dovrebbe essere {1,} o semplicemente + –

+0

@Barry: In molti casi, causerebbe più problemi che risolverli. Mi piacciono le versioni di Brians. @ Brian: Cosa significa il flag/x che non usi nel tuo ultimo comando? –

+0

Perl o Boing non sono cammellati perché non sono parole composte. –

7

Dando per scontato che non si utilizza l'espressione regolare di fare l'estrazione, e solo corrispondenza ...

[A-Z][a-zA-Z]* 

non è l'unico vero requisito che è tutte le lettere e inizia con la lettera maiuscola?

+2

Questo è praticamente equivalente alla regex di Brian tranne che meno complicato. È possibile rilevare parole come HellotheRe, che ovviamente non è corretto CamelCase, ma nessuna espressione regolare può dire che cosa è una parola lì dentro. Basta mettere i segni di confine e questo dovrebbe essere abbastanza buono. – Unknown

+0

MODIFICA: ho corretto la tua espressione regolare capitalizzando la "z" finale. –

+0

@j_random_hacker: whoops. Grazie per averlo capito. –

5

brian's e sharth's risponde anche riferire le parole che consistono interamente in lettere maiuscole (ad esempio FOO). Questo può o non può essere quello che vuoi. Se si desidera limitare al solo parole cammello-carter che contengono almeno una lettera minuscola, uso:

/\b[A-Z][a-zA-Z]*[a-z][a-zA-Z]*\b/ 

Se in aggiunta si desidera escludere parole che consistono di una singola lettera maiuscola seguita da un numero qualsiasi di lettere minuscole (es Perl), uso:

/\b[A-Z][a-zA-Z]*(?:[a-z][a-zA-Z]*[A-Z]|[A-Z][a-zA-Z]*[a-z])[a-zA-Z]*\b/ 

(sostanza, si richiedono la stringa di iniziare con una lettera maiuscola e contenere almeno una lettera maiuscola aggiuntivo e una lettera minuscola; questi ultimi due possono apparire in qualsiasi ordine.)

+0

Il tuo primo esempio corrisponde a cose che non sono parole composte, come "Foo". Il secondo è un po 'peloso per il golf mattutino. :) –

+0

@brian: Come sai, con espressioni regolari è spesso il caso di "alcuni capelli richiesti". :) Spero che dal paragrafo 2 del testo del corpo sia chiaro che la prima espressione regolare corrisponderà a "Foo" et al. (poiché lo scopo della seconda regex è specificamente quello di escludere quelle corrispondenze). –

0

Che ne dici di questo: /\b[A-Z]([a-z]+[A-Z]?)*\b/ ??

+0

Qual è la differenza chiave del tuo codice per Brian's? –

Problemi correlati