Re: Matching encoded strings and file names

[email protected] (John Delacour)
Newsgroups perl.unicode
Message-ID <p06230900bfd1f87e9caa@[10.0.0.1]>
At 10:46 am +0100 20/12/05, [email protected] wrote:

>...Let's say I have a txt file which contains a list of strings. 
>Some of these strings contain characters encoded in this fashion:
>
>R\xC3\xA9union (\xC3\xA9 is one character - e with an accent).

To be more specific \xC3\xA9 represents in escaped form the UTF-8 
transformation of the _precomposed_ form of e with an acute accent -- 
a single character.

>   I also have directory which contains many files, some of which
>also contain these special characters. What I would like to do
>is find any strings from the txt file that match file names in
>the directory. I have tried the following. Assuming
>'R\xC3\xA9union' is in $in and the current file name from the
>directory is in $file:
>
>$in =~ s/\\x(..)/chr(hex($1))/eg;

If you evaluate "\xC9\xA9" then you get _two characters,which, when 
converted internally to UTF-8 will become 5 bytes; not what you want 
at all!  You need first of all to evaluate the whole string, eg:

         #!/usr/bin/perl
         $ascii = 'R\xC3\xA9union';
         $utf8 =  eval qq~"$ascii"~;
         print $utf8;

But that may not be the end of it because, at least on the Mac, file 
names do not use the precomposed form of accented characters, so a 
file named "Réunion" is (in UTF-16) not "R\x{00E9}union" (0xC3A9) but 
"R\x{0065}\x{0301}"

         #!/usr/bin/perl
         binmode STDOUT, ":utf8";
         print "1. R\x{00E9}union" . $/ . "2. R\x{0065}\x{0301}union"

Others may have some magic solution but to me it seems you have to 
convert the escaped original text to the utf-8 bytes it intends, 
convert these to UTF-16BE and then produce one file with the contents 
in precomposed form and another in decomposed form.  Which of these 
you use will depend on the normalisation used in the file system.


#!/usr/bin/perl
use Encode 'from_to';
use Unicode::Normalize;
$xtext = 'R\xC3\xA9union';
$dir = $ENV{HOME};
$junk_hex_escaped = "$dir/junk_hex_escaped.txt";
$junk_precomposed = "$dir/junk_precomposed.txt";
$junk_decomposed = "$dir/junk_decomposed.txt";
open HEXESCAPED, ">$junk_hex_escaped" or die $!;
print HEXESCAPED $xtext;
close HEXESCAPED;
open HEXESCAPED, $junk_hex_escaped or die $!;
open PRECOMPOSED, ">:utf8", $junk_precomposed or die $!;
open DECOMPOSED, ">:utf8", $junk_decomposed or die $!;
while (<HEXESCAPED>){
   $_ = eval qq~"$_"~;
   from_to ($_, "UTF-8", "UTF-16BE");
   ($precomposed, $decomposed) = (NFC($_), NFD($_));
   print PRECOMPOSED $precomposed;
   print DECOMPOSED $decomposed;
}
`open -e $junk_precomposed $junk_decomposed`
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.