如何为Unicode字符串生成由相同宽度的空白字符组成的“幻像”字符串?

时间:2018-09-02 14:47:08

标签: unicode language-agnostic whitespace

给定一系列Unicode字符,我如何获得一串具有相同宽度的空格字符(至少在等宽字体中,这些字体以Basic Latin中的单个或两倍宽度显示每个字符)?

示例

例如,给定字符串'\ u0061 \ u0020 \ u0062 \ u0020 \ u0063',其中包含五个字符,如下所示:

a b c

('a',space,'b',space,'c'),我想获得一个仅包含五个空格的字符串:

\u0020\u0020\u0020\u0020\u0020

,并给定\u6b22\u8fce\u5149\u4e34

欢迎光临

我想获取一个包含四个表意空格的字符串:\u3000\u3000\u3000\u3000

背景

这里是一个重要的示例:针对支持Unicode的语言的编译器中的错误报告。假设我们有一些假设的编程语言 PL (可以是Python,Java,Scala,Ruby ...),其中包含字符串文字和括号。假设这是 PL -code的无效代码段,因为其中包含不匹配的括号:

"stringLiteral")

如果我们尝试对其进行编译,则 PL 的编译器可能会产生如下错误消息:

:1: error: ';' expected but ')' found.
   "stringLiteral")
                  ^

请注意,最后一行中的“幻影字符串”后跟'^':它精确地指向了不匹配的右括号。

如果我对CJK字符尝试相同,这就是我得到的:

:1: error: ';' expected but ')' found.
   "欢迎光临欢迎光临欢迎光临欢迎光临欢迎光临欢迎")
                           ^

请注意,现在最后一行中的“幻影字符串”由普通的拉丁空格组成,在控制台中,'^'看起来好像位于CJK字符字符串的中间,而不是放在括号中。

如果我尝试对克罗地亚字符进行相同操作:

:1: error: ';' expected but ')' found.
   "DŽDždžLJLjljNJNjnj")
              ^

'^'指针的结尾也似乎完全错误,因为这些特殊的克罗地亚字符比普通空格宽得多。

所有示例在Python,Java,Scala和Ruby等语言中都产生相似的结果(只需将" y⃝e҈s҉ ")"临欢迎光临欢迎")复制粘贴到交互式外壳中,然后查看{{1} }结束)。

解决方案尝试

这是在Scala中生成“幻像”字符串的幼稚尝试。有一种方法Character.isIdeographic。通过将每个表意字符映射到^,并将所有其他字符映射到phantom(普通空间),我可以使用它来定义\u3000方法。

' '

在简单的情况下,它可以工作。例如,如果我定义一个字符串

def phantom(s: String) = 
  s.map(c => if (Character.isIdeographic(c)) '\u3000' else ' ')

,然后打印字符串,后跟竖线val s = "foo欢迎光临欢迎bar光临欢baz" ,换行符,然后再打印|和竖线phantom(s)

|

然后我得到:

println(s + "|\n" + phantom(s) + "|")

和字符串末尾的竖线完美对齐,因为foo欢迎光临欢迎bar光临欢baz|            | 现在是

phantom(s)

即:

  • 与“ foo”相对应的三个普通空格
  • 与“欢迎光临欢迎”文章相对应的六个表意空间
  • 然后再次对应于“ bar”的三个空格
  • ...

以此类推。

但是,如果我尝试对克罗地亚语字符进行同样的操作,则会再次陷入混乱:

\u0020\u0020\u0020\u3000\u3000\u3000\u3000\u3000\u3000\u0020\u0020\u0020\u3000\u3000\u3000\u0020\u0020\u0020

(竖线不对齐)。

问题

Unicode是否定义了允许我生成相同宽度的健壮“幻像”字符串的任何属性?

0 个答案:

没有答案