2017-05-03 4 views
2
#!/usr/bin/perl -T 
use strict; 
use warnings; 
use utf8; 
my $s = shift || die; 
$s =~ s/[^A-Za-z ]//g; 
print "$s\n"; 
exit; 

> ./poc.pl "El Guapö" 
El Guap 

Est-il possible de modifier ce code Perl afin que les divers accents et trémas de caractère ne sont pas dépouillé? Merci!chaîne Strip permettent trémas

+2

Bien sûr, les ajouter à la classe de caractères? – sln

+0

Voulez-vous conserver par ex. Caractères chinois? – melpomene

+1

Vous souciez-vous de combiner les accents? Par exemple. Si vous avez LA LETTRE MINUSCULE LATINE O suivie de LA DIAERÈSE COMBINÉE, voulez-vous les garder toutes les deux? – melpomene

Répondre

7

Pour la question directe, vous pouvez tout simplement besoin \p{L} (Lettre) Unicode Character Property

Cependant, plus important encore, décoder tous vos commentaires et encode sortie.

use warnings; 
use strict; 
use feature 'say'; 

use utf8; # allow non-ascii (UTF-8) characters in the source 

use open ':std', ':encoding(UTF-8)'; # for standard streams 

use Encode qw(decode_utf8);   # @ARGV escapes the above 

my $string = 'El Guapö'; 
if (@ARGV) { 
    $string = join ' ', map { decode_utf8($_) } @ARGV; 
} 
say "Input:  $string"; 

$string =~ s/[^\p{L} ]//g; 

say "Processed: $string"; 

Exécuté comme   script.pl 123 El Guapö=_

 
Input:  123 El Guapö=_ 
Processed: El Guapö 

Je l'ai utilisé la "couverture" \p{L} propriété (Lettre), comme description spécifique fait défaut; ajuster si/comme nécessaire. Les propriétés Unicode fournissent beaucoup, voir le lien ci-dessus et la liste complète au perluniprops.

L'espace entre 123 El reste, peut-être des espaces de début de bande (et de fin) à la fin. Notez qu'il existe également \P{L}, où P indique la négation.


ci-dessus simple d'esprit \pL ne fonctionnera pas avec Combining Diacritical Marks, comme la marque sera également supprimé. Merci à jm666 pour le signaler. Cela se produit lorsqu'un caractère "logique" accentué (ce qui apparaît comme un seul caractère) est écrit en utilisant des caractères séparés pour son caractère de base et pour des marques sans espacement (combinant les accents). Souvent, un seul caractère (extended grapheme cluster) avec son codepoint existe également. Exemple: en niño le ñ est U+OOF1 mais il peut également être écrit "n\x{303}".

Pour garder accents écrit ainsi ajouter \p{Mn} (\p{NonspacingMark}) à la classe de caractères

my $string = "El Guapö=_ ni\N{U+00F1}o.* nin\x{303}o+^"; 
say $string; 

(my $nodiac = $string) =~ s/[^\pL ]//g;  #/ naive, accent chars get removed 
say $nodiac; 

(my $full = $string) =~ s/[^\pL\p{Mn} ]//g; # add non-spacing mark 
say $full; 

de sortie

 
El Guapö=_ niño.* niño+^ 
El Guapö niño nino 
El Guapö niño niño 

Vous voulez s/[^\p{L}\p{Mn} ]//g afin de garder les accents de combinaison.

+1

@ jm666 Merci pour le commentaire. Je n'étais pas très concerné par la regex exacte, puisque le PO ne dit pas grand chose - et je pensais que le reste était vraiment plus important. Vous avez raison, vous devez ajouter '\ pM' dans la classe de caractères ... ajoutera, avec un exemple. – zdim

+0

Je comprends un peu. Mon but ultime est de désamorcer l'entrée CGI, stocker dans MySQL, puis récupérer et utiliser en HTML. Ma confusion réside dans le décodage/encodage. Est-il approprié de stocker la valeur décodée dans la base de données et de l'encoder avant utilisation?J'ai besoin de travailler correctement avec les trucs farfelus des clients que je retire actuellement. Merci! –

+0

@TimothyB. Vous l'avez en arrière. Vous devez * en * code avant de le stocker dans la base de données et * de * code lorsque vous le retirez à nouveau. Si vous utilisez DBI et que votre base de données et votre handle de base de données sont correctement configurés, ceci est fait pour vous. –