[Python 人:我的问题在最后:-)]
我想在 C 字符串文字中使用 UTF-8 以提高可读性和易于维护。然而,这不是普遍便携的。我的解决方案是创建一个文件 foo.c.in
,它由一个小的 perl 脚本转换为文件 foo.c
,以便它包含 \xXX
转义序列而不是大于或等于 0x80 的字节。
为简单起见,我假设 C 字符串在同一行开始和结束。
这是我创建的 Perl 代码。如果找到 >= 0x80 的字节,原始字符串也会作为注释发出。
use strict;
use warnings;
binmode STDIN, ':raw';
binmode STDOUT, ':raw';
sub utf8_to_esc
{
my $string = shift;
my $oldstring = $string;
my $count = 0;
$string =~ s/([\x80-\xFF])/$count++; sprintf("\\x%02X", ord($1))/eg;
$string = '"' . $string . '"';
$string .= " /* " . $oldstring . " */" if $count;
return $string;
}
while (<>)
{
s/"((?:[^"\\]++|\\.)*+)"/utf8_to_esc($1)/eg;
print;
}
例如输入
"fööbär"
转换为
"f\xC3\xB6\xC3\xB6b\xC3\xA4r" /* fööbär */
最后,我的问题是:我的 Perl 不是很好,我想知道是否有可能以更优雅(或更“Perlish”)的方式重写代码。我还希望有人能指出用 Python 编写的类似代码。
最佳答案
我认为最好不要使用
:raw
。您正在处理文本,因此您应该正确解码和编码。这将大大减少出错的可能性,并且如果您愿意,它将允许您的解析器使用预定义的字符类。你在解析时就好像你希望在文字中出现斜杠,但是当你转义时你完全忽略了斜杠。因此,您最终可能会得到
"...\\xC3\xA3..."
。使用解码后的文本也会有所帮助。
所以忘记“perlish”;让我们实际修复错误。
use open ':std', ':locale';
sub convert_char {
my ($s) = @_;
utf8::encode($s);
$s = uc unpack 'H*', $s;
$s =~ s/\G(..)/\\x$1/sg;
return $s;
}
sub convert_literal {
my $orig = my $s = substr($_[0], 1, -1);
my $safe = '\x20-\x7E'; # ASCII printables and space
my $safe_no_slash = '\x20-\x5B\x5D-\x7E'; # ASCII printables and space, no \
my $changed = $s =~ s{
(?: \\? ( [^$safe] )
| ( (?: [$safe_no_slash] | \\[$safe] )+ )
)
}{
defined($1) ? convert_char($1) : $2
}egx;
# XXX Assumes $orig doesn't contain "*/"
return qq{"$s"} . ( $changed ? " /* $orig */" : '' );
}
while (<>) {
s/(" (?:[^"\\]++|\\.)*+ ")/ convert_literal($1) /segx;
print;
}
关于python - 良好的 Perl 风格 : How to convert UTF-8 C string literals to\xXX sequences,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18169016/