2009-03-09 11 views
5

Je suis à la recherche d'une regex Perl qui va mettre en majuscule tout caractère précédé d'un espace (ou le premier caractère de la chaîne).Quelle regex va mettre en majuscule les lettres qui suivent un espace?

Je suis assez sûr qu'il ya un moyen simple de faire cela, mais je n'ai pas mon livre Perl pratique et je ne fais pas cela assez souvent que je l'ai appris par cœur ... il

+0

Qu'essayez-vous de faire? Si vous essayez de faire des choses du cas? Il y a un perlfaq pour ça. –

+0

demander sur SO est plus rapide, et je suis sûr que cela va profiter à quelqu'un d'autre quelque part dans le monde une fois que google l'indexe. Je n'utilise pas Perl assez souvent que je peux me souvenir de tous les petits trucs que je connaissais – Kip

Répondre

8

En fonction de votre problème, cela pourrait être plus compliqué que vous ne le pensez et une simple regex pourrait ne pas fonctionner. Avez-vous pensé à la capitalisation à l'intérieur du mot? Et si le mot commence par la ponctuation comme '... Word'? Y a-t-il des exceptions? Qu'en est-il des personnages internationaux?

Il peut être préférable d'utiliser un module CPAN tel que Text::Autoformat ou Text::Capitalize où ces problèmes ont déjà été résolus. Il semble que Text :: Autoformat soit plus "standard" et j'essaierais cela en premier. Il est écrit par Damian. Mais Text :: Capitalize fait quelques choses que Text :: Autoformat ne fait pas. Voici un comparison.

Vous pouvez également consulter le Perl Cookbook pour recipie 1.14 (page 31) sur la façon d'utiliser les expressions rationnelles pour mettre correctement en majuscule un titre ou un titre.

+0

Ceci est un bon point sur la ponctuation étant un problème potentiel. –

+0

merci, ceci est très utile – Kip

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

Je l'origine suggéré:

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

mais cloches d'alarme allaient descendre à l'utilisation de « $& » (même avant d'avoir lu @ commentaire de Manni). Il s'avère qu'ils sont entièrement justifiés - en utilisant les opérations $ &, $ `et $ 'provoquent une inefficacité globale dans les expressions rationnelles.

Le \ E n'est pas critique pour cette regex; il désactive le commutateur \U dans ce cas ou \L pour les minuscules.


Comme il est indiqué dans les commentaires, correspondant au premier caractère de la chaîne nécessite:

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

position corrigée de seconde parenthèse fermante - merci, Blixtor.

+0

vous avez oublié le premier caractère de la chaîne: s/(\ s | ^) \ w/\ U $ &\E/g; – Node

+0

Je n'ai jamais vu une regex comme ça - pouvez-vous l'expliquer? –

+0

$ &? "L'utilisation de cette variable n'importe où dans un programme impose une pénalité de performance considérable sur toutes les correspondances d'expressions régulières." – innaM

7

Quelque chose comme ça devrait faire l'affaire -

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

Cela divise simplement l'expression balayée en deux matchs - $ 1 pour le blanc/début de chaîne et de 2 $ pour le premier caractère de mot. Nous remplaçons alors $ 1 et $ 2 après avoir fait le début du mot majuscule. Je voudrais changer le \ s en \ b, ce qui est plus logique puisque nous vérifions les limites de mots ici.

0

Vous souhaitez faire correspondre des lettres derrière des espaces ou au début d'une chaîne.

Perl ne peut pas effectuer de recherche de longueur variable.Si elle l'a fait, vous auriez pu utiliser ceci:

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

Perl se plaint:

Variable length lookbehind not implemented in regex; 

Vous pouvez utiliser le double lookbehind négatif pour se déplacer que: la chose à gauche de celui-ci ne doit pas être quelque chose que ce n'est pas un espace. Cela signifie qu'il va correspondre au début de la chaîne, mais si il y a quelque chose en face de lui, il doit y avoir des espaces.

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

L'approche la plus simple dans ce cas précis sera probablement juste de correspondre à l'espace; la restriction de longueur variable disparaît alors et l'inclut dans le remplacement.

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

De temps en temps vous ne pouvez pas utiliser cette approche dans les substitutions répétées parce que ce qui précède le match réel a déjà été mangée par l'expression rationnelle, et il est bon d'avoir un moyen de contourner cela.

+0

Vous êtes corrects que '/ (? <= \ S | ^) (\ w) /' ne fonctionne pas, mais notez que '/ (?: (? <= \ S) |) (\ w)/'est une alternative équivalente qui fonctionne. –

1

Ce n'est pas quelque chose que je normalement utiliser une expression régulière pour, mais ma solution est pas exactement ce que vous appelez « belle »:

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

Ce split() s la chaîne par des espaces et capture toutes l'espace, puis passe à travers chaque élément de la liste et fait ucfirst sur eux (en faisant le premier caractère majuscule), puis join() s leur ensemble en une seule chaîne. Pas terrible, mais peut-être que vous aimerez mieux une regex. Personnellement, je n'aime pas \Q ou \U ou d'autres constructions regex semi-maladroites.

EDIT: Quelqu'un d'autre a mentionné que la ponctuation pourrait être un problème potentiel. Si, par exemple, vous voulez ceci:

...string 

changé à ceci:

...String 

-à-dire que vous voulez les mots en majuscules, même s'il y a des signes de ponctuation devant eux, essayer quelque chose comme ceci:

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

La même chose, mais split() s sur les mots (\w+) de sorte que les éléments capturés de la liste ne sont que des mots. Même effet global, mais mettra en majuscule les mots qui ne commencent pas par un caractère de mot. Remplacez \w par [a-zA-Z] pour éliminer la tentative de mise en majuscule des chiffres. Et juste généralement le modifier comme vous le souhaitez.

+0

@Volomike - Quelle version de Perl utilisez-vous? –

+0

Oh tirer. C'était Perl? Ma faute! :) Je vais supprimer mon commentaire. Je pensais que c'était PHP. – Volomike

1

Si vous voulez dire un caractère après l'autre, utilisez des expressions régulières en utilisant \s. Si vous voulez vraiment dire le premier caractère dans le mot, vous devriez utiliser \b au lieu de toutes les tentatives ci-dessus avec \s qui est sujette aux erreurs.

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

Attendez ... \ s est une erreur? Explique ce que tu veux dire et pourquoi tu le penses. –

+0

\ s n'est pas sujette aux erreurs si les conditions indiquent des majuscules après les espaces. Le \ b est aussi un problème. Voyez le cas de Perlfaq sur le fait de faire des choses pour un exemple. –

+0

Les mots ne commencent pas toujours après l'espace. Par exemple: 'algorithme de Levenberg - Marquardt'. Il y a deux mots qui ne commencent pas après l'espace, ni Levenberg ni Marquardt. –

0

Capitaliser tout caractère précédé par des espaces ou au début de la chaîne:

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

Peut-être une manière très bâclée de le faire parce qu'il est aussi uppercasing les espaces blancs maintenant.: P L'avantage est qu'il fonctionne avec des lettres avec tous les accents possibles (et aussi avec des lettres spéciales danoises/suédoises/norvégiennes), ce qui pose problème lorsque vous utilisez \ w et \ b dans votre regex. Puis-je m'attendre à ce que toutes les non-lettres ne soient pas touchées par le modificateur majuscule?

Questions connexes