我有字符串 "re\x{0301}sume\x{0301}" (打印如下:简历),我想将其反转为 "e\x{0301}muse\x{0301}r" (émusér)。我不能使用 Perl reverse 因为它对待组合字符就像 "\x{0301}" 作为单独的角色,所以我最终得到 "\x{0301}emus\x{0301}er" (́emuser)。如何反转字符串,但仍然尊重组合字符?

有帮助吗?

解决方案

最好的答案是以使用 Unicode::GCString, 作为南指出


我修改Chas的例子有点:

  • 设置编码标准输出,以避免"多样的字符印刷"警告;
  • 使用一个积极的lookahead assertion(而不是分隔的保留模式)在 split (不工作之后5.10,显然的,所以我去掉它)

它基本上是同样的事情与一对夫妇的调整。

use strict;
use warnings;

binmode STDOUT, ":utf8";

my $original = "re\x{0301}sume\x{0301}";
my $wrong    = reverse $original;
my $right    = join '', reverse split /(\X)/, $original;

print <<HERE;
original: [$original]
   wrong: [$wrong]
   right: [$right]
HERE

其他提示

您可以使用 \X 特殊转义 (匹配非组合字符和所有以下组合字符)与 split 要制作字素列表(它们之间有空字符串),请反转字素列表,然后 join 他们重新聚在一起:

#!/usr/bin/perl

use strict;
use warnings;

my $original = "re\x{0301}sume\x{0301}";
my $wrong    = reverse $original;
my $right    = join '', reverse split /(\X)/, $original;
print "original: $original\n",
      "wrong:    $wrong\n",
      "right:    $right\n";

可以使用的Unicode :: GCString

  

的Unicode :: GCString对待Unicode字符串由Unicode标准定义的扩展字形簇的序列附件#29 [UAX#29]。

#!/usr/bin/env perl

use utf8;
use strict;
use warnings;
use feature 'say';
use open qw(:std :utf8);

use Unicode::GCString;

my $x = "re\x{0301}sume\x{0301}";
my $y = Unicode::GCString->new($x);
my $wrong = reverse $x;
my $correct = join '', reverse @{ $y->as_arrayref };

say "$x -> $wrong";
say "$y -> $correct";

输出:

résumé -> ́emuśer
résumé -> émusér

其他的一些答案包含不能很好地工作元素。下面是Perl的5.12和5.14测试工作的例子。未按指定binmode将导致输出产生的错误信息。正在以分流的正前向断言(并且没有分离器保留模式)将导致输出是对我的MacBook不正确。

#!/usr/bin/perl

use strict;
use warnings;
use feature 'unicode_strings';

binmode STDOUT, ":utf8";

my $original = "re\x{0301}sume\x{0301}";
my $wrong    = reverse $original;
my $right    = join '', reverse split /(\X)/, $original;
print "original: $original\n",
      "wrong:    $wrong\n",
      "right:    $right\n";
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top