Riempire le stringhe Unicode con printf di bash

Sep 13 2020

Ho provato a riempire una stringa Unicode con printf di bash e l'ho visto, mentre

printf "%2s" a

restituisce la "a" attesa,

una variante Unicode

printf "%2s" ä  

restituisce una "ä" sorprendentemente non imbottita. (zsh dà il risultato atteso.)

Cosa causa questo; e come dovrei riempire le stringhe Unicode in bash?

Risposte

crackpot Sep 13 2020 at 00:02

come dovrei riempire le stringhe Unicode in bash?

Questo è ben oltre le capacità di bash. Se stai limitando le "stringhe Unicode" ad ascii ++ (nessun carattere a doppia larghezza, nessun bidi, nessun segno di non spaziatura, no ecc.), Puoi giudicare qualcosa come:

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

Il carattere äè codificato con 2 byte in UTF-8, quindi Printf lo prende per 2-riempito.

Wc può contare i caratteri ( -m) e i byte ( -c) di una stringa. Il numero da dare a Printf è quindi [intended pad]+[bytes]-[chars]. Quindi ho assemblato questo pad.shscript,

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

Nell'esempio di esecuzione riportato di seguito, ho aggiunto in modo artificiale i newline dopo ogni output per motivi di chiarezza.

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

bash si comporta correttamente e il programma C.

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

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

si comporta lo stesso.

Questo perché% s si riferisce a una stringa orientata ai byte e 'ä' in UTF-8 restituisce 2 byte.

Per quanto ho potuto testare, nessuna delle altre shell si comporta in modo errato.

Il risultato che ti aspetti potrebbe essere visto con qualcosa del tipo:

printf '%2S\n' ä

ma questo non è supportato da nessuna delle shell che ho testato.