次の簡単なスクリプトを実行すると:
#!/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
つまり、発音区別符号付きのテキスト(例:)は、ü
発音区別符号ごとに1文字ずつ「縮小」されます。
もちろん、どこかに間違った設定がありますが、どの設定がわかりません。
これは、ファイルエンコーディングがUTF-8の場合に発生します。
エンコーディングをlatin-1に変更すると、ソートは正確ですが、ウムラウトレンダリングエラーが発生します。
Fr�chte und Gem�se foo
Milchprodukte bar
12345678901234567890 baz
ベストアンサー1
POSIX必要 printf
%-20s
20個を数えましょうバイトいいえ数値printf
印刷とは関係ありませんが、テキスト、書式設定(議論を参照オースティングループでは(POSIX)とbash
メーリングリスト)。
組み込みのprintf
POSIXシェルbash
と他のほとんどのPOSIXシェルはそれに従います。
zsh
この愚かな要件(シミュレーションでもsh
)を無視すると、期待printf
どおりに機能します。printf
組み込みと同じですfish
(POSIXに似たシェルではありません)。
UTF-8でエンコードされると、文字ü
(U + 00FC)は2バイト(0xc3と0xbc)で構成され、これらの違いを説明します。
$ printf %s 'Früchte und Gemüse' | wc -mcL
18 20 18
文字列は18文字で構成され、幅は18列(入力で最も広い行の表示幅を報告するための-L
GNU拡張)ですが、20バイトにエンコードされています。wc
zsh
または では、fish
テキストが正しくソートされます。
幅0の文字(U + 0308などの文字の組み合わせ、分音記号の結合など)やアジアの多くのスクリプト(Tabなどの制御文字は言うまでもありません)のように、幅が2倍の文字もあり、正しく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システムでは、awk
GNUの文字数を文字単位で使用できますprintf
(バイトではなく表示幅ではないため、幅が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"