Erreur de commande introuvable dans l'affectation des variables Bash

521

J'ai ce script appelé test.sh:

#!/bin/bash
STR = "Hello World"
echo $STR

quand je cours sh test.shje reçois ceci:

test.sh: line 2: STR: command not found

Qu'est-ce que je fais mal? Je regarde des tutoriels de script bash extrêmement basiques / débutants en ligne et voici comment ils disent de déclarer des variables ... Donc je ne suis pas sûr de ce que je fais mal.

Je suis sur Ubuntu Server 9.10. Et oui, bash est situé à /bin/bash.

Jake Wilson
la source
49
Je suis content que vous ayez posé la question, vous n'êtes pas le seul noh bash là-bas!
Miller the gorilla
6
Merci d'avoir posé cette question. Ce n'est pas une question à embarrasser. Je travaille tard le soir au bureau et il n'y a aucun expert Bash autour de moi pour répondre à cela.
Adway Lele
3
Ces jours-ci (près de sept ans plus tard!), Il existe un analyseur / analyseur FOSS appelé shellcheck qui détectera automatiquement cela et d'autres problèmes de syntaxe courants. Il peut être utilisé en ligne ou installé hors ligne et intégré dans votre éditeur.
cet autre gars
Je vous recommande d'utiliser: #!/usr/bin/env bashau lieu de mettre directement à #!/bin/bashmoins que vous ne soyez absolument sûr de votre bashprésence à /bincause de cette réponse: stackoverflow.com/a/21613044/3589567
Alejandro Blasco

Réponses:

929

Vous ne pouvez pas avoir d'espaces autour de votre signe «=».

Lorsque vous écrivez:

STR = "foo"

bash essaie d'exécuter une commande nommée STR avec 2 arguments (les chaînes '=' et 'foo')

Lorsque vous écrivez:

STR =foo

bash essaie d'exécuter une commande nommée STR avec 1 argument (la chaîne '= foo')

Lorsque vous écrivez:

STR= foo

bash essaie d'exécuter la commande foo avec STR défini sur la chaîne vide dans son environnement.

Je ne sais pas si cela aide à clarifier ou s'il s'agit d'une simple obfuscation, mais notez que:

  1. la première commande est exactement équivalent à: STR "=" "foo",
  2. le second est le même que STR "=foo",
  3. et le dernier est équivalent à STR="" foo.

La section pertinente de la spécification de langage sh, la section 2.9.1 indique:

Une "commande simple" est une séquence d'affectations et de redirections de variables facultatives, dans n'importe quelle séquence, éventuellement suivie de mots et de redirections, terminée par un opérateur de contrôle.

Dans ce contexte, a wordest la commande que bash va exécuter. Toute chaîne contenant =(dans une position autre qu'au début de la chaîne) qui n'est pas une redirection est une affectation de variable, tandis que toute chaîne qui n'est pas une redirection et ne contient pas =est une commande. Dans STR = "foo", STRn'est pas une affectation de variable.

William Pursell
la source
2
Si vous avez une variable avec un nom qui contient "-", la même erreur se produit. Dans ce cas, la solution est de supprimer le "-"
chomp
1
chomp @ Dans la règle 7b de la section 2.10.10 de pubs.opengroup.org/onlinepubs/9699919799 "Si tous les caractères précédant '=' forment un nom valide (voir Nom XBD), le jeton ASSIGNMENT_WORD doit être retourné." En suivant le lien vers la section 3.231 de pubs.opengroup.org/onlinepubs/9699919799 , nous trouvons "Dans le langage de commande du shell, un mot composé uniquement de traits de soulignement, de chiffres et d'alphabets du jeu de caractères portable. Le premier caractère d'un nom est pas un chiffre. ". Le mot FOO-BAR=quxn'est donc pas une affectation de variable car ce FOO-BARn'est pas un nom valide.
William Pursell
2
J'offre une prime pour récompenser cette explication claire d'un problème toujours commun pour les débutants (enfin, et aussi pour pouvoir le trouver plus rapidement chaque fois que je veux le lier: D). Merci d'avoir rendu les choses aussi simples!
fedorqui 'SO arrête de nuire'
1
@fedorqui Merci! Je ne suis pas entièrement convaincu qu'il s'agit d'une explication claire, et je me demande souvent si cela pourrait être simplifié.
William Pursell
159

Déposez les espaces autour du =panneau:

#!/bin/bash 
STR="Hello World" 
echo $STR 
Joey
la source
9
C'est drôle, cependant, tout comme set foo = barune erreur courante dans les fichiers batch de Windows - et là, le langage batch est ridiculisé pour cela ;-)
Joey
Merci @joey. J'étais coincé dans l'écriture d'un script shell où j'initialisais des variables avec des espaces après "=". Vous m'avez sauvé la journée
Lalit Rao
Pourquoi bash n'accepte pas les nombres dans le champ de gauche? comme 3 = "Hello World", il se plaint d'une commande introuvable
Freedo
6

En mode interactif, tout va bien:

$ str="Hello World"
$ echo $str
Hello World

Évidemment (!) Comme l'a dit Johannes, pas d'espace autour =. Dans le cas où il y a de l'espace =dans le mode interactif, cela donne des erreurs comme

Aucune commande «str» trouvée

Arkapravo
la source
2
Mais notez le PO disait STR = "Hello World", donc cette réponse ne s'applique pas ici.
fedorqui 'SO stop harming'
@Arkapravo quelle est la signification du mode interactif, est-ce que cela a quelque chose à voir avec la $marque
Kasun Siyambalapitiya
@KasunSiyambalapitiya par "mode interactif", il signifie taper ces commandes dans le terminal réel, pas dans un script.
numbermaniac
5

Je sais que cela a été répondu par une réponse de très haute qualité. Mais, en bref, vous ne pouvez pas avoir d'espace.

#!/bin/bash
STR = "Hello World"
echo $STR

N'a pas fonctionné à cause des espaces autour du signe égal. Si vous deviez courir ...

#!/bin/bash
STR="Hello World"
echo $STR

Ça marcherait

Derek Haber
la source
2

Lorsque vous définissez une variable, vous n'avez pas besoin de mettre d'espace supplémentaire.

Par exemple

name = "Stack Overflow"  
// it is not valid, you will get an error saying- "Command not found"

Supprimez donc les espaces:

name="Stack Overflow" 

et cela fonctionnera bien.

Ravi Solanki
la source