Bash'ın printf ile unicode dizelerini doldurma

Sep 13 2020

Bir Unicode dizesini bash'ın printf ile doldurmayı denedim ve bunu gördüm.

printf "%2s" a

beklenen "a" değerini verir,

bir Unicode varyantı

printf "%2s" ä  

şaşırtıcı bir şekilde dolgusuz bir "ä" verir. (zsh, beklenen sonucu verir.)

Buna ne sebep olur; ve Unicode dizelerini bash'ta nasıl dolduracağım?

Yanıtlar

crackpot Sep 13 2020 at 00:02

bash'ta Unicode dizelerini nasıl dolduracağım?

Bu, bash'ın yeteneklerinin çok ötesinde. "Unicode dizelerini" ascii ++ ile sınırlıyorsanız (çift genişlikli karakterler yok, bidi yok, boşluk bırakmayan işaretler yok, vb.), Aşağıdaki gibi bir jüri donanımı uygulayabilirsiniz:

% pad(){ printf '%*s%s\n' "$(($1-${#2}))" "" "$2"; }
% pad 2 €
 €
Quasímodo Sep 13 2020 at 00:06

Karakter äUTF-8'de 2 bayt ile kodlanmıştır, bu nedenle Printf onu 2-dolgulu olarak alır.

Wc, bir dizenin karakterlerini ( -m) ve baytlarını ( -c) sayabilir . Printf'e verilecek numara o zaman [intended pad]+[bytes]-[chars]. Bu yüzden bu pad.shsenaryoyu bir araya getirdim ,

#!/bin/sh
bytes=$(printf '%s' "$2" | wc -c)
chars=$(printf '%s' "$2" | wc -m)
n=$(($1+bytes-chars))
printf "%${n}s" "$2"

Aşağıdaki örnek uygulamada, netlik uğruna her çıktıdan sonra yapay olarak yeni satırlar ekledim.

$ sh pad.sh 10 abcdef abcdef $ sh pad.sh 10 äéßôçÈ
    äéßôçÈ
schily Sep 12 2020 at 23:48

bash düzgün davranır ve C programı

#include <stdio.h>
main()
{
        char foo[] = "ä";

        printf("%2s\n", foo);
}

aynı şekilde davranır.

Bunun nedeni,% s'nin bayt yönelimli bir dizgeye başvurması ve UTF-8'deki 'ä' ifadesinin 2 bayt ile sonuçlanmasıdır.

Test edebildiğim kadarıyla, diğer mermilerin hiçbiri yanlış davranmıyor.

Beklediğiniz sonuç aşağıdaki gibi bir şeyle görülebilir:

printf '%2S\n' ä

ancak bu, test ettiğim kabukların hiçbiri tarafından desteklenmiyor.