python - 良好的 Perl 风格 : How to convert UTF-8 C string literals to\xXX sequences

标签 python c perl utf-8 string-literals

[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 编写的类似代码。

最佳答案

  1. 我认为最好不要使用 :raw。您正在处理文本,因此您应该正确解码和编码。这将大大减少出错的可能性,并且如果您愿意,它将允许您的解析器使用预定义的字符类。

  2. 你在解析时就好像你希望在文字中出现斜杠,但是当你转义时你完全忽略了斜杠。因此,您最终可能会得到 "...\\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/

相关文章:

c - 提前退出 C 语言的整个程序?

perl - 编写以下内容的更简洁方法

python - Py3 : Can't open file/snapshot/serverless/lib/plugins/aws/invokeLocal/invoke. py:没有那个文件或目录

Python - 将列表范围设置为特定值

c - 使用循环平铺从矩阵中提取子矩阵

c - C 中另一个结构体内部的结构体

perl - 在Windows中使用dos批处理程序的原因是什么?

perl - 如何检查哪种检查端口状态的方法更有效?

python - 如何在Python中按第一个和最后一个字符拆分字符串

python - Pandas 按名称和最近日期合并