2009-03-09 18 views
5

Sto cercando un'espressione regolare Perl che capitalizzerà qualsiasi carattere preceduto da spazi bianchi (o il primo carattere nella stringa).Quali regex capitalizzeranno le lettere che seguono lo spazio bianco?

sono abbastanza sicuro che ci sia un modo semplice per fare questo, ma io non ho il mio libro Perl a portata di mano e io non farlo abbastanza spesso che ho memorizzato che ...

+0

Cosa stai cercando di fare? Se stai cercando di rendere le cose con titolo? C'è un perlfaq per quello. –

+0

chiedere su SO è più veloce, e sono sicuro che andrà a beneficio di qualcun altro da qualche parte nel mondo una volta che Google lo indicizza. non uso perl abbastanza spesso da ricordare tutti i piccoli trucchi che conoscevo – Kip

risposta

8

A seconda del tuo problema, questo potrebbe essere più complicato di quanto pensi e una semplice regex potrebbe non funzionare. Hai mai pensato alla capitalizzazione all'interno della parola? Cosa succede se la parola inizia con la punteggiatura come '... Parola'? Ci sono delle eccezioni? Che dire dei personaggi internazionali?

Potrebbe essere preferibile utilizzare un modulo CPAN come Text::Autoformat o Text::Capitalize in cui questi problemi sono già stati risolti.

use Text::Capitalize 0.2; 
print capitalize_title($t), "\n"; 

use Text::Autoformat; 
print autoformat{case => "highlight", right=>length($t)}, $t; 

Sembra che Text :: Autoformat potrebbe essere più "standard" e lo proverei prima. È scritto da Damian. Ma Text :: Capitalize fa alcune cose che Text :: Autoformat non ha. Ecco uno comparison.

È anche possibile controllare lo Perl Cookbook per la destin. 1.14 (pagina 31) su come utilizzare espressioni regolari per capitalizzare correttamente un titolo o un titolo.

+0

Questo è un buon punto sul fatto che la punteggiatura sia un potenziale problema. –

+0

grazie, questo è abbastanza utile – Kip

10
s/(\s\w)/\U$1\E/g; 

originariamente ho suggerito:

s/\s\w/\U$&\E/g; 

ma allarme campane stavano andando fuori a l'uso di '$&' (anche prima di leggere @ commento di Manni). Si scopre che sono pienamente giustificati: l'uso delle operazioni $ &, $ `e $ 'causa un'inefficienza generale delle espressioni regolari.

La \ E non è critica per questa espressione regolare; disattiva l'interruttore "case case" \U in questo caso o \L per la lettera minuscola.


Come notato nei commenti, corrispondente al primo carattere della stringa richiede:

s/((?:^|\s)\w)/\U$1\E/g; 

posizione corretto del secondo vicino parentesi - grazie, Blixtor.

+0

hai dimenticato il primo carattere della stringa: s/(\ s | ^) \ w/\ U $ &\E/g; – Node

+0

Non ho mai ho visto una regex del genere - puoi spiegarlo? –

+0

$ &? "L'uso di questa variabile ovunque in un programma impone una notevole penalizzazione delle prestazioni su tutte le partite di espressioni regolari." – innaM

7

Qualcosa del genere dovrebbe fare il trucco -

s!(^|\s)(\w)!$1\U$2!g 

Questo divide semplicemente l'espressione scansionato in due partite - $ 1 per il bianco/inizio di corda e $ 2 per il primo carattere della parola. Sostituiamo quindi $ 1 e $ 2 dopo aver fatto l'inizio della parola maiuscola.

Vorrei cambiare i \ s in \ b che ha più senso dal momento che stiamo controllando i limiti delle parole qui.

0

Si desidera abbinare le lettere dietro agli spazi bianchi o all'inizio di una stringa.

Perl non può eseguire una ricerca di lunghezza variabile.Se così fosse, si potrebbe avere usato questo:

s/(?<=\s|^)(\w)/\u$1/g; # this does not work! 

Perl si lamenta:

Variable length lookbehind not implemented in regex; 

È possibile utilizzare doppio lookbehind negativo per aggirare questo: la cosa a sinistra di esso non deve essere tutto ciò che non è uno spazio Ciò significa che corrisponderà all'inizio della stringa, ma se c'è qualcosa di fronte ad esso, deve essere spazio bianco.

s/(?<!\S)(\w)/\u$1/g; 

L'approccio più semplice in questo caso esatto sarà probabilmente quello di abbinare semplicemente lo spazio bianco; la restrizione di lunghezza variabile cade, quindi, e include quella nella sostituzione.

s/(\s|^)(\w)/$1\u$2/g; 

Di tanto in tanto non si può utilizzare questo approccio in sostituzioni ripetute perché che ciò che precede la partita reale è già stata mangiata dal regex, ed è bello avere un modo per aggirare questo.

+0

Sei corretto che '/ (? <= \ S | ^) (\ w) /' non funziona, ma nota che '/ (?: (? <= \ S) | ^) (\ w)/'è un'alternativa equivalente che funziona. –

1

questo non è qualcosa che avrei normalmente si usa un'espressione regolare per, ma la mia soluzione non è esattamente quello che si chiama "bello":

$string = join("", map(ucfirst, split(/(\s+)/, $string))); 

Che split() s la stringa da spazi bianchi e cattura tutte lo spazio bianco, quindi passa attraverso ogni elemento della lista e fa ucfirst su di loro (rendendo il primo carattere maiuscolo), quindi join() s loro di nuovo insieme come una singola stringa. Non terribile, ma forse ti piacerà più una regex. Personalmente non mi piace il \Q o \U o altri costrutti regex semi-imbarazzanti.

MODIFICA: qualcun altro ha affermato che la punteggiatura potrebbe essere un potenziale problema. Se, per esempio, si desidera che questo:

...string 

cambiato a questo:

...String 

per esempio, si desidera che le parole in maiuscolo, anche se non c'è la punteggiatura prima di loro, provare qualcosa di più simile a questo:

$string = join("", map(ucfirst, split(/(\w+)/, $string))); 

Stessa cosa, ma è split() s su parole (\w+) in modo che gli elementi catturati dell'elenco siano di sola parola. Lo stesso effetto generale, ma capitalizzerà le parole che potrebbero non iniziare con un carattere di parola. Modificare \w a [a-zA-Z] per eliminare il tentativo di utilizzare i numeri maiuscoli. E solo generalmente modificarlo come preferisci.

+0

@Volomike - Quale versione di Perl stai usando? –

+0

Oh sparare. Quello era Perl? Colpa mia! :) Cancellerò il mio commento. Pensavo fosse PHP. – Volomike

1

Se si intende carattere dopo spazio, utilizzare le espressioni regolari utilizzando \s. Se si intende veramente il primo carattere in una parola, è necessario utilizzare \b anziché tutti i tentativi di cui sopra con \s che è soggetto a errori.

s/\b(\w)/\U$1/g; 
+0

Attendi ... \ s è soggetto a errori? Spiega cosa intendi e perché lo intendi. –

+0

\ s non è soggetto ad errori se i requisiti dicono in maiuscolo cose che si trovano dopo lo spazio bianco. Anche \ b è un problema. Vedi il perlfaq su come rendere le cose con titolo title per un esempio. –

+0

Le parole non iniziano sempre dopo lo spazio. Ad esempio: 'Levenberg - Algoritmo Marquardt'. Ci sono due parole che non iniziano dopo lo spazio, né Levenberg né Marquardt. –

0

capitalizza gli carattere preceduto da spazi bianchi o all'inizio di stringa:

s/(^|\s)./\u$1/g 

Forse un modo molto scrupoloso di farlo perché è anche il maiuscolo gli spazi ora.: P Il vantaggio è che funziona con lettere con tutti gli accenti possibili (e anche con lettere speciali danesi/svedesi/norvegesi), che sono problematiche quando si usano \ w e \ b nella regex. Posso aspettarmi che tutte le non lettere non siano toccate dal modificatore in maiuscolo?

Problemi correlati