2010-05-22 10 views
1

J'utilise SCIM sous Linux pour les entrées en chinois et en japonais. Malheureusement, lorsque j'essaie de capturer l'entrée en utilisant le STDIN de Perl, l'entrée est folle. Comme les caractères romains sont tapés, SCIM essaie de deviner les caractères finaux corrects. Les codes H (retour arrière) sont utilisés pour supprimer les caractères suggérés précédemment sur la ligne de commande. (Au fur et à mesure que vous tapez, SCIM essaie de deviner les caractères asiatiques finaux et les affiche.) Cependant, ces caractères de retour arrière sont affichés littéralement comme^H et ne sont pas interprétés correctement.Comment capturer l'entrée chinoise via SCIM avec STDIN en Perl?

Exemple one-liner:

perl -e 'print "Chinese: "; my $s = <STDIN>; print $s' 

Quand activer chinois SCIM ou entrée de langue japonaise, comme je tape, par exemple, nihao => 你好, voici le résultat:

你^ H 你^H 你^H H^H 你好^H^H 你好^H^H 你好^H^H 你 H^H^H 你 H^H^H 你 H^H^H At^H^H H^H^H 你好^H^H 你好

À la toute fin de cette chaîne, vous pouvez voir "好 »(nihao/bonjour). À une invite bash normale, si je tape nihao (avec chinois activé), les résultats sont parfaits.

Cela a quelque chose à voir avec l'interprétation des caractères de retour arrière (ou des caractères de contrôle) au cours de STDIN de Perl. La même chose se produit lors de l'utilisation de la commande 'read' dans Bash.

Témoin: read -p 'Chinese: ' s && echo $s

+0

Je pense que vous pourriez avoir besoin de dire à Perl quel est le codage sur stdin. Je ne sais pas sur le dessus de ma tête si comment faire cela. : | –

+0

@Robert P: 'binmode STDIN,": encodage (UTF-8) ";'. Mais je ne pense pas que ce soit le problème ici. –

+0

Essayez 'read -ep 'Chinese:' s && echo $ s' pour voir si l'utilisation de' readline' affecte les choses. –

Répondre

3

Le problème est que vous avez besoin quelque chose à interpréter les caractères backspace. L'invite bash normale le fait. Si vous avez désactivé SCIM et que vous avez tapé ca<BACKSPACE>ot<ENTER>, il semblerait que vous ayez tapé cot, mais Perl le verrait ca^Hot.

Vous pouvez utiliser un package readline complet (tel que Term::ReadLine et un backend approprié) ou vous pouvez simplement corriger les chaînes après les avoir lues. Il y a un module Clean::Backspace qui fait cela, mais il ne semble pas être Unicode-safe, ce qui le rend à peu près inutilisable pour cette application.

Voici un coup d'œil à un code qui devrait fonctionner:

my $s = <STDIN>; 
1 while $s =~ s/(?!\cH)\X\cH//g; # Delete character-backspace pair 
print $s; 

Vous voudrez probablement faire un sous-programme pour gérer cela.