给定一系列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)
即:
以此类推。
但是,如果我尝试对克罗地亚语字符进行同样的操作,则会再次陷入混乱:
\u0020\u0020\u0020\u3000\u3000\u3000\u3000\u3000\u3000\u0020\u0020\u0020\u3000\u3000\u3000\u0020\u0020\u0020
(竖线不对齐)。
问题
Unicode是否定义了允许我生成相同宽度的健壮“幻像”字符串的任何属性?