J'ai eu ce comportement étrange ce matin dans un terminal bash:
user@home:/home/user$ [ -f /etc/openvpn/client.conf ] && echo true
bash: [: missing «]»
user@home:/home/user$ [ -f /etc/openvpn/client.conf ] && echo true
true
- La première commande a été collée à partir d'un script édité avec gedit.
- Le second a été tapé directement dans le terminal.
Après quelques recherches, je découvre qu'en supprimant le 30ème caractère (l'espace entre client.conf et "]") et en le remplaçant par un espace, la commande a de nouveau fonctionné.
Mon hypothèse était juste: un caractère vierge inconnu s'est glissé dans la commande , mais la question est:
- Comment puis-je révéler ces caractères dans le terminal afin de pouvoir déboguer la commande? Et plus important encore:
- Comment puis-je empêcher que cela se reproduise?
BTW, j'exécute Ubuntu 18.04 / langue française, le script à partir duquel je colle la commande est dans un lecteur USB et peut avoir été modifié sur Windows aussi.
Merci pour vos très bonnes réponses. Le mauvais caractère est un caractère UTF-8 d'espace insécable c2 a0 . La question Comment supprimer le caractère spécial 'M-BM-' avec sed a un fait intéressant à propos de ce caractère.
Ce qui est étrange, c'est que le script est exempt de ce personnage. Donc je ne sais pas d'où ça vient.
la source
history 2|xxd
(car lahistory
commande elle-même est toujours la dernière de la liste), ou tapezhistory|grep "CommandWithProblem"|xxd
. Vous pouvez utiliser n'importe quel autre programme d'affichage hexadécimal au lieu dexxd
, mais cela correspond par défaut à un format que j'aime.set -x
. Cela vous montrerait la commande et comment elle est divisée. Cela ne signifierait pas nécessairement «mauvais personnage ici», mais cela vous montrerait que bash ne se divisait pas sur ce personnage.Réponses:
Une option consiste à regarder les personnages que vous essayez d'utiliser avec une visionneuse ou un éditeur hexadécimal.
hexdump
est une bonne option si vous êtes limité au terminal.Vous pouvez voir ici que
space
,close-square-brace
,space
sont corrects -0x20
,0x5D
,0x20
.Ces valeurs sont des codes ASCII, affichés en hexadécimal . Toute valeur en dehors de la plage
0x20
-0x7E
n'est pas un " caractère imprimable " en ce qui concerne ASCII, et ne fonctionnera probablement pas bien avec les interfaces de ligne de commande.Remarque: J'ai copié votre première ligne " brisée " pour l'utiliser dans le
hexdump
exemple ci-dessus, donc quelque chose a remplacé l' espace non-ASCII par un espace ASCII entre votre source d'origine et votre question rendue.Pour répéter cela, procédez comme suit:
hexdump -Cv <<"EOF"
et appuyez surEnterEOF
votre propre ligne et appuyez surEnterLes terminaux et les interfaces de ligne de commande ne gèrent pas bien les caractères spéciaux - comme vous l'avez découvert. Si vous n'êtes pas très prudent avec la mise en forme des documents, vous aurez également des problèmes avec Microsoft Word (et d'autres) en utilisant " guillemets intelligents ", des tirets em, la liste continue ...
Repérez la différence: (le haut est " citations intelligentes ", le bas est " citations droites ")
Ici, les citations ouvertes ne sont pas une citation simple ASCII (
"
), mais sont un Unicode / UTF-8 série -0xE2
,0x80
,0x9C
ouU+201C
- que le terminal ne traitera pas comme on pouvait s'y attendre.La suggestion de Kiwy fait
cat -A
également l'affaire:Remarque: lors de l'utilisation
echo "..." | hd
, vous avez une chance que bash substitue des parties de la chaîne que vous essayez d'inspecter. Cela est particulièrement préoccupant lorsque vous essayez d'inspecter les composants d'un script.Par exemple, essayez:
Ces méthodes remplacent les composants par le texte correspondant. Pour éviter cela, utilisez l'une des approches suivantes. Notez l'utilisation de guillemets simples (
'
) et d'un " hérédoc entre guillemets " ("EOF"
).la source
echo "[ -f /etc/openvpn.ovpn ]" | hd
retourne[...] c2 a0 [...]
. Nous pouvons voir l' espace insécable du caractère C2 A0 UT-8Vous pouvez utiliser
cat
avec l'-A
option: du manuel:Alors
cat -A yourscrip.sh
vous montrer des personnages invisibles et étranges.la source
echo "[ -f /etc/openvpn.ovpn ]" | cat -A
retourne[ -f /etc/openvpn/client.ovpnM-BM- ]$
. Nous pouvons voir l' espace insécable du personnage M-BM- UT-8echo "<your command>" | hd
devrait marcher. Recherchez le retour arrière (0x08) ou les caractères avec des codes> = 80.echo "<your command>" | wc -b
et vérifier que le nombre correspond à ce que vous voyez est également une bonne idée.Copier des trucs à partir de fichiers produits par n'importe quoi avec "Office" dans son nom est dangereux, car un tel logiciel prend souvent la liberté de remplacer les caractères: en français, recherchez les guillemets remplacés par "guillemets", en anglais pour les guillemets simples remplacés par leur ouvrir / fermer des équivalents. Le plus difficile que j'ai jamais trouvé était un espace insécable de largeur 0 au milieu d'un nom de fichier (3 jours d'arrêt du serveur ...).
la source
hd
c'est court pourhexdump
ce qui est également mentionné dans la réponse d'Attie.hd
est équivalent àhexdump -C
.echo "[ -f /etc/openvpn.ovpn ]" | hd
retourne[...] c2 a0 [...]
. Nous pouvons voir l' espace insécable du caractère C2 A0 UT-8Bash, et d'autres shells comme zsh, peuvent ouvrir la ligne de commande actuelle dans un éditeur. Le raccourci par défaut pour bash est
C-x C-e
( CtrlX CtrlE), et il s'ouvre dans le premier disponible de$VISUAL
,$EDITOR
et emacs. En pratique, cela est inestimable pour le débogage et la modification de commandes complexes. Selon la façon dont vous le regardez, zsh est plus convivial que bash ici: lorsque l'éditeur se ferme, bash exécute la commande immédiatement, tandis que zsh attend que vous appuyiez Enter(vous donnant plus de chances de modifier la commande).Après avoir ouvert la commande dans un éditeur, vous pouvez configurer vos éditeurs pour afficher différemment les caractères non ASCII.
Par exemple, avec Vim , en utilisant ces paramètres:
Ou, en adaptant les méthodes des autres réponses:
la source