printf:多字节字符

use*_*001 6 bash character-encoding printf

当尝试格式化printf包含多字节字符的字符串的输出时,很明显printf不计算文字字符而是字节数,如果混合单字节和多字节字符,这会使格式化文本变得困难。例如:

$ cat script
#!/bin/bash
declare -a a b
a+=("0")
a+=("00")
a+=("000")
a+=("0000")
a+=("00000")
b+=("0")
b+=("??00")
b+=("??000")
b+=("??0000")
b+=("??00000")
printf "%-15s|\n" "${a[@]}" "${b[@]}"

$ ./script
0              |
00             |
000            |
0000           |
00000          |
0              |
??00       |
??000      |
??0000     |
??00000    |
Run Code Online (Sandbox Code Playgroud)

我发现了各种建议的解决方法(主要是使用另一种语言或实用程序来打印文本的包装器)。是否有任何本机 bash 解决方案?任何记录的printf 格式字符串似乎都没有帮助。locale在这种情况下,这些设置是否相关,例如,使用像 UTF-32 这样的固定宽度字符编码?

iga*_*gal 2

我做了一些网络搜索,但我无法在纯 Bash 中找到你的问题的解决方案,而且我认为可能没有。我发现了以下 StackOverflow 帖子:

\n\n\n\n

那里得票最高的答案(由用户tchrist发布)包括以下内容:

\n\n
\n

printf是的,这是我所知道的所有版本的问题。我在这个答案和这个答案中简要讨论了这个问题。

\n
\n\n

我还在 Unix StackExchange 上发现了以下帖子:

\n\n\n\n

那里接受的解决方案包括以下解释:

\n\n
\n

POSIX要求 printf\'s以字节%-20s而不是字符来计算这 20 个字符,尽管这与printf打印格式化文本没有什么意义(请参阅Austin Group (POSIX) 和bash邮件列表中的讨论)。

\n
\n\n

看来您想要做的事情可能无法实现,printf并且您必须推出自己的解决方案。

\n\n

我能够使用 Python 脚本生成所需的输出。也许你会发现它很有用:

\n\n
#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n"""script.py"""\n\n# Set the default character encoding to UTF-8\nimport sys\nreload(sys)\nsys.setdefaultencoding("utf-8")\n\n# Array of ASCII characters\na=[("0")]\na+=[("00")]\na+=[("000")]\na+=[("0000")]\na+=[("00000")]\n\n# Array of UTF-8 Characters\nb=[("0")]\nb+=[("\xe2\x94\x9c\xe2\x94\x8000")]\nb+=[("\xe2\x94\x9c\xe2\x94\x80000")]\nb+=[("\xe2\x94\x9c\xe2\x94\x800000")]\nb+=[("\xe2\x94\x94\xe2\x94\x8000000")]\n\n# Print the elements from both arrays\nfor x in a + b:\n    print (u"%-15s|" % x).encode(\'utf-8\')\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是我运行脚本时得到的结果:

\n\n
user@host:~$ python script.py\n\n0              |\n00             |\n000            |\n0000           |\n00000          |\n0              |\n\xe2\x94\x9c\xe2\x94\x8000           |\n\xe2\x94\x9c\xe2\x94\x80000          |\n\xe2\x94\x9c\xe2\x94\x800000         |\n\xe2\x94\x94\xe2\x94\x8000000        |\n
Run Code Online (Sandbox Code Playgroud)\n