2009-10-09 5 views
1

Je suis en train de supprimer/supprimer le second dernier caractère d'un script tibétain, comme indiqué ci-dessous (caractère dans l'exemple suivant sont l'anglais):expression régulière Perl de dans un script tibétain

$char = "ti.be.tan.|";   

Je veux supprimer le caractère "second last" "." J'ai essayé de la manière suivante avec mes quelques connaissances de RE:

$char =~ s/.|$/|/g; 
$char =~ s/[.|]$/|/g; 
$char = tr/.|//d;  # and later add |. 

Qu'est-ce que je fais mal?

Répondre

8

Avant de vous dire ce que vous devez faire droit, regardons ce que vous faites mal:

$char =~ s/.|$/|/g; 

Le problème ici est que les deux . et | sont métacaractères dans les expressions régulières. Le | signifie "ou", vous dites donc "correspondre . ou $". Vous savez correctement que $ signifie la fin de la chaîne, mais . signifie "n'importe quel caractère." Il correspond donc immédiatement à un caractère et continue de correspondre immédiatement à un caractère, en changeant ce caractère à | (les métacaractères ne s'appliquent pas dans la seconde moitié de l'expression s///), puis il correspond à la fin de la chaîne et ajoute | là-bas. Ou quelque chose comme ça. Fondamentalement, pas ce que vous voulez arriver.

$char =~ s/[.|]$/|/g; 

Eh bien, à l'intérieur [] s, . et | arrêt étant métacaractères, mais [] signifie « un de ceux-ci, » si cette expression régulière recherche le caractère avant la fin de la chaîne, et si elle est soit | ou ., il le change en |. Encore une fois, pas ce que vous voulez arriver.

$char = tr/.|//d;  # and later add |. 

tr est le mauvais outil pour ce travail. Cela supprimerait tous les caractères . et | dans votre chaîne, attendez-vous à ce que vous n'utilisiez pas l'opérateur de correspondance regex =~, mais l'opérateur d'affectation =. Certainement pas ce que vous voulez arriver.

Ce que vous voulez est ceci:

$char =~ s/\.\|$/|/; 

Nous avons échappé à la fois la . et la | avec un \ si Perl connaît « le caractère après la \ est un caractère littéral sans signification particulière * » et correspond à .| à la fin de votre chaîne et la remplace par |.

Cela dit, il semble que vous soyez un peu nouveau dans les expressions régulières. Je suis un grand fan de perldoc perlretut, qui je pense est l'un des meilleurs (sinon le meilleur) introduction aux expressions régulières en Perl. Vous devriez vraiment le lire - les expressions régulières sont un outil puissant dans les mains de ceux qui les connaissent, et un mal de tête puissant pour ceux qui ne les connaissent pas.

+2

Merci ... Les deux "." et "|" n'êtes pas le personnage auquel vous faites référence. J'ai donné ces deux exemples comme "Tibet Unicode charater 0F0B (.) Et OFOD (|). Merci de m'avoir indiqué la documentation de Perl – Cthar

+1

Vous aurez probablement besoin d'utiliser des échappements Unicode pour obtenir le même effet. Je ne sais pas le tibétain, mais je parie que les pages d'expressions rationnelles 'perldoc' traiteront de ce problème à un moment donné –

+0

Le livre d'O'Reilly sur les expressions rationnelles est assez bon aussi –

3

Chris Lutz a déjà fourni une excellente réponse, donc je veux juste fournir une réponse supplémentaire au cas où vous voudriez supprimer le deuxième caractère d'un autre type de chaîne.

Ici, il est:

$char =~ s/(.)(.)$/\2/g;

Fondamentalement, Perl (actally RegEx) pointera tout entre '(' et ')' aux groupes. Lequel vous pourrez manipuler ce groupe plus tard. De ce code les gourps sont.

$char =~ s/(.)(.)$/\2/g; 
#   ^-^^-^ ^^ 
# Capture G1 G2 ++-- Then replace it with only group 2 

Donc dans ce cas, Perl va du premier caractère, car il n'a pas retourné aucun résultat, il laisse aller (remplacer), quand il se trouve un match, il remplace le match avec ce que vous avez spécifié (dans ce le cas est le groupe n ° 2).

Espérons que cela aide.

+1

Les échappements' \ 2' sont obsolètes et généreront un avertissement si vous «utilisez des avertissements» (ce que je suis sûr que vous faites toujours: P) .Vous devriez utiliser '$ 2' à la place –

+3

pour clarifier, ils sont obsolètes sur le côté droit de s ///, pas à gauche – ysth

+0

Oh vraiment? !!: -o Je l'utilise toujours parce que je l'utilise pour la première fois dans sed.: P – NawaMan

1

Vous pouvez également utiliser substr comme lvalue dans cette situation:

$char = "ti.be.tan.|"; 
substr($char,-2,1) = ""; 
print $char;    # ===> ti.be.tan| 
0

Il y a aussi la méthode utilisant l'affirmation de positif pour enlever préanalyse le second dernier caractère.

$char ~= s/.(?:.$)//; 

Qui lit essentiellement "" pour n'importe quel caractère qui est immédiatement suivi par un seul caractère et la fin de la chaîne.

Si le deuxième caractère est toujours un caractère spécifique, vous pouvez remplacer le premier. N'oubliez pas d'échapper les métacaractères RE() [] /.*?