如何反转包含Perl中的字符组合的字符串?

Cha*_*ens 13 string unicode perl reverse

我有字符串"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"(emuśer).如何反转字符串,但仍然尊重组合字符?

Cha*_*ens 12

您可以使用\ 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";
Run Code Online (Sandbox Code Playgroud)

  • 为了澄清迈克尔的评论,当你在正则表达式中使用内存括号时,你可以触发"分隔符保留模式".你得到了你正在分裂的部分之间的东西.但是,您不需要这样做.模式(?=\X)执行相同的操作,没有额外的位.并不是说空字符串对于小字符串来说真的很重要. (2认同)

bri*_*foy 8

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


我稍微修改了Chas的例子:

  • 在STDOUT上设置编码以避免"打印中的宽字符"警告;
  • 使用正向前瞻断言(并且没有分隔符保留模式)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
Run Code Online (Sandbox Code Playgroud)

  • 神奇?怎么会这样?它只是一个没有副作用的正则表达式,它只是你所看到的.如果您认为这很神奇,那么您还没有看到Perl真正的黑色艺术.你可能会称之为聪明(虽然我不会),但这并不神奇.它可能只是你从未使用过的东西. (2认同)