2009-03-09 9 views
5

Estoy buscando una expresión regular de Perl que capitalice cualquier carácter que esté precedido por espacios en blanco (o el primer carácter en la cadena).¿Qué regex sacará mayúsculas de las letras que siguen al espacio en blanco?

estoy bastante seguro de que hay una manera simple de hacer esto, pero no tengo mi libro de Perl a mano y yo no hago esto con la suficiente frecuencia que he memorizado ...

+0

¿Qué estás tratando de hacer? Si estás tratando de hacer las cosas del caso del título? Hay un perlfaq para eso. –

+0

preguntando por SO es más rápido, y estoy seguro de que beneficiará a alguien más en algún lugar del mundo una vez que google lo indexe. No uso Perl con la frecuencia suficiente como para recordar todos los trucos que solía saber. – Kip

Respuesta

8

Dependiendo de su problema exacto, esto podría ser más complicado de lo que cree y una expresión regular simple podría no funcionar. ¿Has pensado en mayúsculas dentro de la palabra? ¿Qué pasa si la palabra comienza con signos de puntuación como '... Word'? ¿Hay alguna excepción? ¿Qué hay de los personajes internacionales?

Puede ser mejor utilizar un módulo CPAN como Text::Autoformat o Text::Capitalize donde estos problemas ya se han resuelto.

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

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

Parece que Text :: Autoformat podría ser más "estándar" y lo probaría primero. Está escrito por Damian. Pero Text :: Capitalize hace algunas cosas que Text :: Autoformat no hace. Aquí hay un comparison.

También puede consultar Perl Cookbook para recipie 1.14 (página 31) sobre cómo usar expresiones regulares para escribir correctamente un título o título.

+0

Este es un buen punto sobre la posibilidad de que la puntuación sea un problema potencial. –

+0

gracias, esto es bastante útil – Kip

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

originalmente sugerida:

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

pero campanas de alarma se iban en el uso de '$&' (incluso antes de leer el comentario de @ Manni). Resulta que están completamente justificados: usar las operaciones $ &, $ `y $ 'causa una ineficacia general en expresiones regulares.

El \ E no es crítico para esta expresión regular; apaga el interruptor 'case-setting' \U en este caso o \L para minúsculas.


Como se señaló en los comentarios, que coincide con el primer carácter de la cadena requiere:

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

posición corregida del segundo paréntesis de cierre - gracias, Blixtor.

+0

Olvidaste el primer carácter de la cadena: s/(\ s | ^) \ w/\ U $ &\E/g; – Node

+0

Nunca visto una expresión regular como esa, ¿puedes explicarlo? –

+0

$ &? "El uso de esta variable en cualquier lugar de un programa impone una penalización de rendimiento considerable en todas las coincidencias de expresiones regulares". – innaM

7

Algo como esto debe hacer el truco -

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

Esto simplemente divide la expresión digitalizada en dos partidos - $ 1 para el blanco/inicio de la cadena y $ 2 para el primer carácter de la palabra. Luego sustituimos $ 1 y $ 2 después de hacer el inicio de la palabra en mayúscula.

Cambiaría la \ s a \ b, lo que tiene más sentido ya que estamos buscando límites de palabras aquí.

0

Desea hacer coincidir letras detrás de espacios en blanco, o al comienzo de una cadena.

Perl no puede hacer lookbehind de longitud variable.Si así fuera, se podría haber utilizado este:

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

Perl se queja:

Variable length lookbehind not implemented in regex; 

Puede utilizar el doble de búsqueda hacia atrás negativa a conseguir alrededor de eso: la cosa a la izquierda de la misma no debe ser cualquier cosa que no es un espacio en blanco Eso significa que coincidirá al comienzo de la cadena, pero si hay algo delante de él, debe ser un espacio en blanco.

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

El enfoque más simple en este caso exacto probablemente sea simplemente coincidir con el espacio en blanco; la restricción de longitud variable cae, entonces, e incluye eso en el reemplazo.

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

En ocasiones no se puede utilizar este enfoque en sustituciones repetidas debido a que lo que precede al partido real ya se ha comido por la expresión regular, y es bueno tener una forma de evitar eso.

+0

Tiene razón en que '/ (? <= \ S | ^) (\ w) /' no funciona, pero tenga en cuenta que '/ (?: (? <= \ S) | ^) (\ w)/'es una alternativa equivalente que funciona. –

1

Esto no es algo que normalmente haría uso de una expresión regular para, pero mi solución no es exactamente lo que llamarían "bello":

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

Eso split() s por la cadena de espacios en blanco y captura todas las el espacio en blanco, luego recorre cada elemento de la lista y hace ucfirst en ellos (convirtiendo el primer carácter en mayúscula), luego join() s los vuelve a juntar como una sola cuerda. No es horrible, pero quizás te guste una expresión regular más. Personalmente, simplemente no me gustan los \Q o \U u otras construcciones regex semi torpes.

EDITAR: Alguien más mencionó que la puntuación podría ser un problema potencial. Si, por ejemplo, desea que esta:

...string 

cambiado a esto:

...String 

es decir, quiere que las palabras en mayúsculas incluso si no hay puntuacion delante de ellos, a intentar algo más a esto:

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

Lo mismo, pero es split() s en las palabras (\w+) para que los elementos capturados de la lista sean solo palabras. Mismo efecto general, pero se escriben en mayúsculas las palabras que no pueden comenzar con un carácter de palabra. Cambie \w a [a-zA-Z] para eliminar el intentar capitalizar números. Y, en general, modifícalo como quieras.

+0

@Volomike - ¿Qué versión de Perl estás usando? –

+0

Oh disparar. ¿Ese era Perl? ¡Mi error! :) Eliminaré mi comentario. Pensé que era PHP. – Volomike

1

Si quiere decir carácter tras espacio, use expresiones regulares usando \s. Si realmente quiere decir primer personaje en la palabra, debe usar \b en lugar de todos los intentos anteriores con \s que es propenso a errores.

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

Esperar ... \ s es propenso a errores? Explica a qué te refieres y por qué lo dices en serio. –

+0

\ s no es propenso a errores si los requisitos dicen cosas mayúsculas que están después del espacio en blanco. El \ b también es un problema. Vea el perlfaq sobre cómo hacer que las mayúsculas y minúsculas sean un ejemplo. –

+0

Las palabras no siempre comienzan después del espacio. Por ejemplo: 'Levenberg - Algoritmo Marquardt'. Hay dos palabras que no comienzan después del espacio, ni Levenberg ni Marquardt. –

0

mayúscula una carácter precedido por espacios en blanco o al comienzo de la cadena:

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

Tal vez una manera muy descuidada de hacerlo, ya que también está uppercasing el espacio en blanco ahora.: P La ventaja es que funciona con letras con todos los acentos posibles (y también con letras especiales danesas/suecas/noruegas), que son problemáticas cuando usas \ w y \ b en tu expresión regular. ¿Puedo esperar que el modificador en mayúsculas no toque todas las letras que no sean letras?

Cuestiones relacionadas