为什么printf“缩小”变音符号?

蕾妮·尼芬格

如果我执行以下简单脚本:

#!/bin/bash
printf "%-20s %s\n" "Früchte und Gemüse"   "foo"
printf "%-20s %s\n" "Milchprodukte"        "bar"
printf "%-20s %s\n" "12345678901234567890" "baz"

它打印:

Früchte und Gemüse foo
Milchprodukte        bar
12345678901234567890 baz

也就是说,带有变音符号(例如ü)的文本会被每个变音符号“缩小”一个字符。

当然,我在某个地方有一些错误的设置,但是我无法弄清楚可能是哪一个。

如果文件的编码为UTF-8,则会发生这种情况。

如果我将其编码更改为latin-1,则对齐是正确的,但是变音符号却被错误地呈现:

Fr�chte und Gem�se   foo
Milchprodukte        bar
12345678901234567890 baz
斯蒂芬·查泽拉斯(Stephane Chazelas)

POSIX需要 printf%-20s计算这20来讲字节不是字符,即使是没有什么意义,因为printf是打印文本,格式化(见讨论在奥斯汀集团(POSIX)和bash邮件列表)。

POSIX shell和其他大多数POSIX shellprintf内置组件都可以bash证明这一点。

zsh忽略了这个愚蠢的要求(即使在sh仿真中也是如此),因此printf可以按您期望的那样工作。printf内建的相同fish(不是类似POSIX的shell)。

ü以UTF-8编码时字符(U + 00FC)由两个字节(0xc3和0xbc)组成,这说明了差异。

$ printf %s 'Früchte und Gemüse' | wc -mcL
    18      20      18

该字符串由18个字符组成,宽18列(-L是GNUwc扩展,用于报告输入中最宽行的显示宽度),但编码为20个字节。

zsh或中fish,文本将正确对齐。

现在,有些字符的宽度为0(例如,组合字符,如U + 0308,组合偏斜),或者像许多亚洲脚本中一样,其宽度为双倍(更不用说Tab等控制字符了),甚至zsh无法对齐那些正确的。

例如,在zsh

$ printf '%3s|\n' u ü $'u\u308' $'\u1100'
  u|
  ü|
 ü|
  ᄀ|

bash

$ printf '%3s|\n' u ü $'u\u308' $'\u1100'
  u|
 ü|
ü|
ᄀ|

ksh93具有一种%Ls格式说明,可以根据显示宽度来计算宽度。

$ printf '%3Ls|\n' u ü $'u\u308' $'\u1100'
  u|
  ü|
  ü|
 ᄀ|

如果文本包含TAB之类的控制字符,这仍然行不通(怎么可能?printf必须知道制表位在输出设备中的距离以及其开始打印的位置)。它确实偶然地使用了退格字符(例如在roff输出中,X(粗体X)写为X\bX),尽管ksh93考虑到所有控制字符的宽度都为-1

其他选择

在中zsh,您可以使用其填充参数扩展标志(l用于左填充,r用于右填充),当与该m标志结合使用时,将考虑字符的显示宽度(而不是字符串中的字符数):

$ () { printf '%s|\n' "${(ml[3])@}"; } u ü $'u\u308' $'\u1100'
  u|
  ü|
  ü|
 ᄀ|

expand

printf '%s\t|\n' u ü $'u\u308' $'\u1100' | expand -t3

这适用于某些expand实现(尽管不是GNU的)。

在GNU系统中,你可以使用GNUawkprintf计数字符(不是字节,而不是显示宽度,所以仍然为0,宽度或2角字符也不行,但确定为您的样品):

gawk 'BEGIN {for (i = 1; i < ARGC; i++) printf "%-3s|\n", ARGV[i]}
     ' u ü $'u\u308' $'\u1100'

如果输出到终端,则还可以使用光标定位转义序列。喜欢:

forward21=$(tput cuf 21)
printf '%s\r%s%s\n' \
  "Früchte und Gemüse"    "$forward21" "foo" \
  "Milchprodukte"         "$forward21" "bar" \
  "12345678901234567890"  "$forward21" "baz"

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

为什么preg_replace删除变音符号?

来自分类Dev

PHP –为什么显示一些变音符号却不显示?

来自分类Dev

为什么有些变音符号不被删除?

来自分类Dev

为什么有些变音符号不被删除?

来自分类Dev

为什么将具有字符类的String.replace转换为德语变音符号到Binaries?

来自分类Dev

RedirectToAction()打破变音符号

来自分类Dev

不能写变音符号

来自分类Dev

Java删除变音符号

来自分类Dev

Python:删除希腊变音符号/重音符号

来自分类Dev

Qt SQL Server和变音符号

来自分类Dev

无法显示德语变音符号

来自分类Dev

编码变音符号的怪异问题

来自分类Dev

无法验证包含变音符号的文本

来自分类Dev

使用Go删除变音符号

来自分类Dev

变音符号上的Levenshtein距离

来自分类Dev

在列表/集中存储变音符号

来自分类Dev

AngularJs搜索并忽略变音符号

来自分类Dev

从iOS到PHP的变音符号

来自分类Dev

字符串编码变音符号

来自分类Dev

Elasticsearch将变音符号显示为“ ??”

来自分类Dev

Webfont没有变音符号

来自分类Dev

无法验证包含变音符号的文本

来自分类Dev

Qt SQL Server和变音符号

来自分类Dev

Android HttpRequest HttpPost变音符号

来自分类Dev

编码变音符号的怪异问题

来自分类Dev

忽略变音符号的搜索功能

来自分类Dev

无法显示德语变音符号

来自分类Dev

VC ++从流中解码变音符号

来自分类Dev

删除变音符号不起作用