Tengo la cadena "re\x{0301}sume\x{0301}"
(que se imprime así: re & # x0301; sume & # x0301;) y quiero revertirla a "e\x{0301}muse\x{0301}r"
(e & # x0301; muse & # x0301; r). No puedo usar reverse
de Perl porque trata la combinación de caracteres como "\x{0301}"
como caracteres separados, así que termino obteniendo "\x{0301}emus\x{0301}er"
(& # x0301; emus & # x0301; er). ¿Cómo puedo invertir la cadena pero respetar los caracteres combinados?¿Cómo puedo invertir una cadena que contiene la combinación de caracteres en Perl?
Respuesta
La mejor respuesta es utilizar Unicode::GCString, as Sinan points out
he modificado el ejemplo de Chas un poco:
- Establezca la codificación en STDOUT para evitar advertencias de "caracteres anchos en la impresión";
- Use una afirmación de búsqueda positiva hacia delante (y no hay modo de retención del separador) en
split
(no funciona después de 5,10, por lo visto, así que me lo quitó)
Es básicamente el mismo con un par de ajustes.
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
Puede utilizar el \X special escape (que coincida con un carácter que no sea la combinación y todos los siguientes caracteres de combinación) con split
a hacer una lista de grafemas (con cadenas vacías entre ellos), invertir la lista de grafemas, entonces join
vuelta juntos:
#!/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";
Para aquellos confundido (como era en un principio) acerca de por qué existen cadenas vacías entre los grafemas, es porque el 'split' se invierte: utiliza los datos eso es lo que se quiere como separador La cadena vacía es lo que está "entre" dos grafemas. Solo al incluir el separador en el resultado obtendrás los grafemas mezclados con el resultado "real": un montón de cadenas vacías. Un método alternativo (y ligeramente más rápido) que lo evita es usar un 'm // g' para capturar los grafemas en su lugar:' join '', reverse $ original = ~/(\ X)/g' –
Para aclarar el comentario de Michael , cuando utiliza el paréntesis de memoria en una expresión regular que asigna a la división, activa el "modo de retención de separador". Recuperas lo que va entre las partes que estás dividiendo. No es necesario que haga eso sin embargo. El patrón (? = \ X) hace lo mismo sin bits adicionales. No es que la cadena vacía realmente importe tanto para cuerdas pequeñas. –
Tiene razón al señalar "modo de retención de separador", gracias, eso fue útil. Sin embargo, (? = \ X) no es equivalente. Para la prueba, considere estos dos ejemplos: split/(a) /, "abc" no es equivalente a dividir/(? = A) /, "abc" y split/(b + c) /, "abbcd" no es equivalente a split/(? = b + c) /, "abbcd" – Flimm
Algunas de las otras respuestas contienen elementos que no funcionan bien. Aquí hay un ejemplo de trabajo probado en Perl 5.12 y 5.14. Si no se especifica el binmode, la salida generará mensajes de error. Usar una aserción positiva de búsqueda anticipada (y ningún modo de retención de separador) en división causará que la salida sea incorrecta en mi 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";
Puede utilizar Unicode::GCString:
Unicode :: GCString trata cadena Unicode como una secuencia de grupos de grafema extendidos definido por Unicode estándar Anexo # 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";
Salida:
résumé -> ́emuśer résumé -> émusér
- 1. ¿Cómo puedo invertir la caja de una cadena en Java?
- 2. ¿Cómo puedo verificar si una cadena Perl contiene letras?
- 3. Cómo comprobar que la cadena contiene caracteres especiales en ruby
- 4. Contiene(), cómo invertir utilizando lambda
- 5. ¿Cómo puedo encapsular una cadena en Perl?
- 6. Tratar con una cadena que contiene codificaciones de caracteres múltiples
- 7. ¿Cómo puedo adivinar la codificación de una cadena en Perl?
- 8. analizar una cadena que contiene caracteres de escape utilizando Java
- 9. Invertir palabras en una cadena
- 10. ¿Cómo puedo verificar que una cadena contiene una fecha?
- 11. ¿Cómo puedo dividir una cadena en trozos de dos caracteres cada uno en Perl?
- 12. Perl: ordenar caracteres dentro de una cadena
- 13. ¿Cómo puedo preasignar una cadena en Perl?
- 14. Invertir una cadena en C
- 15. ¿Cómo comprobar si una cadena contiene dos caracteres de asterisco?
- 16. Cómo invertir palabras en una cadena?
- 17. Cómo insertar una cadena que contiene un "&"
- 18. ¿Cómo puedo extraer subcadenas de una cadena en Perl?
- 19. últimos caracteres de una cadena K en Perl
- 20. ¿Cómo puedo escapar de caracteres especiales en una cadena que interpolar en una expresión regular de Perl?
- 21. ¿Cómo reconocer si una cadena contiene caracteres unicode?
- 22. ¿Cómo puedo convertir una cadena en un número en Perl?
- 23. ¿Cómo puedo saber que mi cadena contiene signos diacríticos?
- 24. ¿Cómo puedo detectar caracteres Unicode en una cadena de Java?
- 25. Cómo comprobar si una cadena contiene solo caracteres específicos
- 26. ¿Cómo detectar si una cadena contiene caracteres especiales?
- 27. ¿Cómo puedo saber si una cadena contiene caracteres multibyte en Javascript?
- 28. Cómo redirigir a una cadena de consulta URL que contiene caracteres no ASCII en DJANGO?
- 29. JavaScript: cómo eliminar la línea que contiene una cadena específica
- 30. Modificar los dos últimos caracteres de una cadena en Perl
Wow. Me gusta Perl, pero esa expresión dividida es bastante mágica. Mi primer pensamiento fue "fuerza bruta": realice una función para hacer lo que hace la división: devuelva una lista de cadenas, cada una de las cuales representa un carácter lógico. Sin embargo, obtienes esa lista (llámala @x), la parte join ('', reverse (@x)) obviamente sigue, afortunadamente. – Roboprog
¿Mágico? ¿Cómo es eso? Es solo una expresión regular sin efectos secundarios y solo hace exactamente lo que ves. Si crees que eso es magia, no has visto las verdaderas artes negras de Perl. Podría llamarlo inteligente (aunque no lo haría), pero no es mágico. Probablemente sea algo que nunca has usado. –
Intenté ejecutar este ejemplo usando Perl v5.12.4 y no funcionó. Usar/(\ X)/en su lugar lo hizo. Fuera de interés, ¿esta respuesta funcionó en versiones anteriores de Perl, o simplemente nos perdimos lo obvio? – Flimm