web-dev-qa-db-fra.com

L'utilisation de `printf` pour imprimer une variable contenant`% `signe de pourcentage donne" bash: printf: `p ': caractère de format invalide"

Je veux utiliser printf pour imprimer une variable. Il est possible que cette variable contienne un % signe de pourcentage.

Exemple minimal:

$ TEST="contains % percent"
$ echo "${TEST}"
contains % percent
$ printf "${TEST}\n"
bash: printf: `p': invalid format character
contains $

(echo fournit la sortie souhaitée.)

6
finefoot

Utilisez printf dans sa forme normale:

printf '%s\n' "${TEST}"

De man printf:

SYNOPSIS
printf FORMAT [ARGUMENT]...

Vous devez jamais transmettre une variable à la chaîne FORMAT car cela peut entraîner des erreurs et des failles de sécurité.


Btw:

si vous voulez avoir % signez dans le cadre du FORMAT, vous devez saisir %%, par exemple.:

$ printf '%d%%\n' 100
100%
16
pLumo

Vous ne devez jamais mettre de contenu variable dans la chaîne de format donnée à printf. Utilisez-le à la place:

printf '%s\n' "${TEST}"
10
Stephen Kitt

printf prend un paramètre garanti, puis un certain nombre de paramètres supplémentaires en fonction de ce que vous passez. Donc quelque chose comme ça:

printf '%07.2f' 5

se transforme en:

0005.00

Le premier paramètre, appelé "format", est toujours présent. S'il ne contient pas de %strings, c'est simplement imprimé. Donc:

printf Hello

produit simplement Hello (notamment, sans le retour à la ligne echo ajouterait dans son mode par défaut). En s'attendant à ce que votre exemple fonctionne, vous avez été induit en erreur par votre propre abus (inconscient) de ce fait; car vous n'avez passé que des chaînes sans %s dans format, du point de vue de printf, vous ne cessiez de lui demander de produire des choses qui ne nécessitaient aucune substitution, donc cela fonctionnait à peu près comme echo -ne.

Si vous voulez faire cela à droite, vous voulez probablement commencer à former vos chaînes imprimables avec les capacités de substitution intégrées de printf. Des lignes comme celle-ci apparaissent partout dans mon code:

printf '%20s: %6d %05d.%02d%%' "$key" $val $((val/max)) $((val*100/max%100))

Si vous voulez que ce que vous faites actuellement fonctionne, vous voulez echo -ne, ainsi:

TEST="contains % percent"
echo -ne "${TEST}\n"

Cela préserve le comportement (discutable) d'interprétation \ s'échappe à l'intérieur de la variable. Il semble également un peu idiot de fournir -n puis collez le \n de retour, mais je vous le propose car c'est une recherche et un remplacement global que vous pouvez appliquer à tout ce que vous faites actuellement. Une version plus propre qui conserve encore \ les échappements travaillant dans la variable seraient:

TEST="contains % percent"
echo -e "$TEST"
3
BMDan