J'ai la chaîne "re\x{0301}sume\x{0301}"
(qui imprime comme ceci: re & # x0301; sume & # x0301;) et je veux l'inverser à "e\x{0301}muse\x{0301}r"
(e & # x0301; muse & # x0301; r). Je ne peux pas utiliser le reverse
de Perl car il traite des caractères de combinaison comme "\x{0301}"
comme des caractères séparés, donc je finis par obtenir "\x{0301}emus\x{0301}er"
(& # x0301; emus & # x0301; er). Comment puis-je inverser la chaîne, mais toujours respecter les caractères de combinaison?Comment puis-je inverser une chaîne contenant des caractères de combinaison en Perl?
Répondre
La meilleure réponse est d'utiliser Unicode::GCString, as Sinan points out
J'ai modifié l'exemple de Chas un peu:
- Définissez le codage sur STDOUT pour éviter les avertissements "caractères larges dans l'impression";
- Utilisez une assertion avant positive (sans préciser le mode de rétention de séparation) dans
split
(ne fonctionne pas après 5,10, apparemment, donc je l'ai enlevé)
Il est fondamentalement la même chose avec quelques coups secs.
use strict;
use warnings;
binmode STDOUT, ":utf8";
my $original = "re\x{0301}sume\x{0301}";
my $wrong = reverse $original;
my $right = join '', reverse split /(\X)/, $original;
print <<HERE;
original: [$original]
wrong: [$wrong]
right: [$right]
HERE
Vous pouvez utiliser le \X special escape (correspondant à un caractère non-combinaison et tous les caractères combinant suivants) avec split
pour faire une liste des graphèmes (avec des chaînes vides entre eux), inverse la liste des graphèmes, puis les join
retour ensemble:
#!/usr/bin/perl
use strict;
use warnings;
my $original = "re\x{0301}sume\x{0301}";
my $wrong = reverse $original;
my $right = join '', reverse split /(\X)/, $original;
print "original: $original\n",
"wrong: $wrong\n",
"right: $right\n";
Pour les confondre (comme je l'étais au début) de savoir pourquoi il y a des chaînes vides entre les graphèmes, il est parce que le 'split' est inversé: il utilise les données c'est voulu comme séparateur. La chaîne vide est ce qui est "entre" deux graphèmes. C'est seulement en incluant le séparateur dans le résultat que vous obtenez les graphèmes mélangés avec le résultat "réel" - un tas de chaînes vides. Une méthode alternative (et légèrement plus rapide) qui évite cela est d'utiliser un 'm // g' pour capturer les graphèmes à la place:' join ', inverse $ original = ~/(\ X)/g' –
Pour clarifier le commentaire de Michael , lorsque vous utilisez des parenthèses de mémoire dans une regex que vous donnez à split, vous déclenchez le "mode de rétention de séparateur". Vous récupérez la chose qui se passe entre les parties que vous divisez. Vous n'avez pas besoin de faire cela cependant. Le motif (? = \ X) fait la même chose sans bits supplémentaires. Non que la chaîne vide compte vraiment pour les petites chaînes. –
Vous avez raison de souligner "mode de rétention séparateur", merci, cela a été utile. Cependant, (? = \ X) n'est pas équivalent. Pour preuve, considèrent ces deux exemples: split/(a) /, "abc" ne correspond pas à diviser/(? = A) /, "abc" et split/(b + c) /, "abbcd" n'est pas équivalent à split/(? = b + c) /, "abbcd" – Flimm
Certaines des autres réponses contiennent des éléments qui ne fonctionnent pas bien. Voici un exemple de travail testé sur Perl 5.12 et 5.14. Si vous ne spécifiez pas binmode, la sortie générera des messages d'erreur. L'utilisation d'une assertion lookahead positive (et pas de mode de rétention de séparateur) dans split entraînera une erreur de sortie sur mon Macbook.
#!/usr/bin/perl
use strict;
use warnings;
use feature 'unicode_strings';
binmode STDOUT, ":utf8";
my $original = "re\x{0301}sume\x{0301}";
my $wrong = reverse $original;
my $right = join '', reverse split /(\X)/, $original;
print "original: $original\n",
"wrong: $wrong\n",
"right: $right\n";
Vous pouvez utiliser Unicode::GCString:
Unicode :: GCString traite chaîne Unicode comme une séquence de groupes de graphèmes étendues définies par Unicode standard Annexe # 29 [UAX # 29].
#!/usr/bin/env perl
use utf8;
use strict;
use warnings;
use feature 'say';
use open qw(:std :utf8);
use Unicode::GCString;
my $x = "re\x{0301}sume\x{0301}";
my $y = Unicode::GCString->new($x);
my $wrong = reverse $x;
my $correct = join '', reverse @{ $y->as_arrayref };
say "$x -> $wrong";
say "$y -> $correct";
Sortie:
résumé -> ́emuśer résumé -> émusér
- 1. Parsing une chaîne contenant des caractères échappées en Java
- 2. Chaîne multiligne contenant des caractères spéciaux en javascript?
- 3. Comment diviser une chaîne en plusieurs blocs de deux caractères chacun en Perl?
- 4. Traiter une chaîne contenant plusieurs encodages de caractères
- 5. Comment inverser la chaîne en binaire
- 6. Comment puis-je analyser une chaîne contenant des caractères génériques et des classes de caractères dans Ruby?
- 7. Comment puis-je convertir une chaîne en nombre en Perl?
- 8. Comment extraire des caractères uniques ou des groupements fermés à partir d'une chaîne en Perl?
- 9. Comment lire un fichier codé ANSI contenant des caractères spéciaux
- 10. inverser la chaîne
- 11. Comment annuler l'effacement des caractères spéciaux XML en Perl?
- 12. Comment inverser la sortie sed?
- 13. Comment passer des arguments de ligne de commande contenant des caractères spéciaux à un processus lancé via Perl ou Bash?
- 14. comment trouver les fichiers contenant une chaîne en utilisant egrep
- 15. Comment convertir une chaîne binaire en nombre en Perl?
- 16. Comment convertir une chaîne en tableau de caractères dans c (ou) comment extraire une chaîne de caractères char unique?
- 17. Comment échanger des caractères de chaîne en Java?
- 18. Comment séparer une chaîne le long d'un séparateur de chaîne fourni par l'utilisateur en Perl?
- 19. tinyMCE & wordpress donnant des caractères impairs ... combinaison de solutions éprouvée
- 20. Comment séparer une chaîne en deux parties avec Perl?
- 21. Comment diviser une chaîne avec des caractères blancs comme délimiteurs?
- 22. Comment supprimer des caractères particuliers d'une chaîne en utilisant XSLT?
- 23. En Perl, comment savoir si une chaîne est un nombre?
- 24. Comment puis-je répéter une chaîne N fois en Perl?
- 25. Scinder une chaîne en deux caractères dans Ruby
- 26. Comment créer des identifiants uniques en Perl?
- 27. comment itérer des caractères individuels dans une chaîne Lua?
- 28. Inverser le mot de passe django.contrib.auth.models.User, sha1 en chaîne lisible
- 29. Comment puis-je inverser une expression régulière en JavaScript?
- 30. Comment placer un deux-points dans une chaîne de deux caractères à partir de la fin en utilisant Perl?
Wow. J'aime perl, mais cette expression fractionnée est plutôt magique. Ma première pensée était «force brute»: faites une fonction pour faire ce que fait la division - renvoyez une liste de chaînes dont chaque entrée représente un caractère logique. Cependant vous obtenez cette liste (appelez-la @x), la partie jointe ('', reverse (@x)) suit évidemment, heureusement. – Roboprog
Magique? Comment? C'est juste une regex sans effets secondaires et elle ne fait exactement ce que vous voyez. Si vous pensez que c'est de la magie, vous n'avez pas vu les vrais arts noirs de Perl. Vous pourriez l'appeler intelligent (bien que je ne le ferais pas), mais ce n'est pas magique. C'est probablement juste quelque chose que tu n'as jamais utilisé. –
J'ai essayé d'exécuter cet exemple en utilisant Perl v5.12.4 et cela n'a pas fonctionné. En utilisant/(\ X)/a fait. Par intérêt, cette réponse a-t-elle fonctionné dans les versions précédentes de Perl, ou avons-nous simplement manqué l'évidence? – Flimm