Crochets dans la condition if: pourquoi est-ce que j'obtiens des erreurs de syntaxe sans espace blanc?

17

J'utilise le script ci-dessous pour reculer de deux jours lorsque le script s'exécute au début de deux jours de l'année et également vérifier les premier et deuxième jours de chaque mois et reculer de deux jours.

if [$month="01"] && [$day="01"];
then
    date="$last_month/$yes_day/$last_year"
      fulldate="$last_month/$yes_day/$last_year"
else
if [$month="01"] && [$day="02"];
then
         date="$last_month/$yes_day/$last_year"
      fulldate="$last_month/$yes_day/$last_year"
else
   if [ $day = "01" ];
then
    date="$last_month/$yes_day/$year"
            fulldate="$year$last_month$yes_day"
else
        if [ $day = "02" ];
then
    date="$last_month/$yes_day/$year"
        fulldate="$year$last_month$yes_day"
else
    date="$month/$yes_day/$year"
        fulldate="$year$month$yes_day"
                fi
               fi
              fi
fi

Mais ma mauvaise reçoit le message d'erreur ci-dessous

Etime_script.sh: line 19: [06=01]: command not found
Etime_script.sh: line 24: [06=01]: command not found
Kumar1
la source
1
Les réponses données sont correctes; vous avez besoin d'espaces après [. En outre, examinez l' elifinstruction; cela vous aidera à nettoyer les choses. En outre, les points-virgules après les instructions if ne sont pas nécessaires, mais ne sont pas non plus incorrects, juste étranges.
Shawn J. Goff
@ ShawnJ.Goff Ils sont nécessaires si vous concaténez la ligne suivante ( if [ ... ]; then), donc pas si inhabituel.
goldilocks
@goldilocks, oui, c'est mon style préféré. La raison pour laquelle c'est inhabituel est qu'il ne le fait pas.
Shawn J. Goff

Réponses:

27

[n'est ni un métacaractère ni un opérateur de contrôle (pas même un mot réservé; même pour ]), il a donc besoin d'espaces autour. Sinon , le shell « voit » la commande au [01=01]lieu de la commande [avec les paramètres séparés 01, =, 01et ]. Chaque opérateur et opérande doit être un argument distinct de la [commande, donc des espaces sont également nécessaires autour des opérateurs.

if [ "$month" = "01" ]

[$month="01"]est un motif générique correspondant à l'un des caractères de $monthou "01. Si cela ne correspond à rien, il est laissé seul.

S'il y a un point-virgule après le crochet de fermeture, vous n'avez pas besoin d'espace avant, car le point-virgule fait toujours partie d'un jeton distinct.

if [ "$month" = "01" ]; then

Il en va de même pour la syntaxe double crochet de bash (et ksh et zsh).

Plus d'une condition

Il existe deux façons de combiner des conditions:

  1. dans [

  2. avec des [commandes séparées combinées avec &&ou||

Le regroupement avec des crochets est probablement plus facile à l'intérieur [.

if [ "$month" = "01" -a "$day" = "01" ] # -a for and, -o for or

if [ "$month" = "01" ] && [ "$day" = "01" ]

Le premier doit être évité car il n'est pas fiable (essayez par exemple avec month='!'). Les problèmes de contenu de variable étrange peuvent être évités en utilisant d'abord la chaîne de sécurité (s'il y en a une); ou en utilisant [[/ ]]au lieu de [/ ]:

if [ "01" = "$month" -a "01" = "$day" ]
Hauke ​​Laging
la source
Comment nous pouvons faire correspondre les deux conditions dans if, comme la valeur du mois == la valeur du jour si [$ month = "01"] && [$ day = "01"]; je m'attends à 01 && 01 true puis imprimer sous les conditions ou passer à la déclaration else
Kumar1
@AshokSanganahalli J'ai étendu ma réponse.
Hauke ​​Laging
1
[quand -a/ -one sont pas utilisés est toujours fiable avec des shells conformes POSIX. Il n'y a aucun avantage à utiliser -a/-oOver &&/||. Je découragerais certainement son utilisation. Notez que ce [[n'est pas POSIX.
Stéphane Chazelas
4

Une autre façon de l'écrire:

case $month:$day in
  (01:0[12])
    date="$last_month/$yes_day/$last_year"
    fulldate="$last_month/$yes_day/$last_year"
    ;;
  (*:0[12])
    date="$last_month/$yes_day/$year"
    fulldate="$year$last_month$yes_day"
    ;;
  (*)
    date="$month/$yes_day/$year"
    fulldate="$year$month$yes_day"
esac
Stéphane Chazelas
la source
1
+1 pour la casedéclaration. Si vous en avez plus d'un elif, vous devriez probablement l'utiliser case.
HalosGhost
-1

Voici donc votre réponse:

if [ $var1 == $var2 ];
 then
    echo "bla bla"
fi

Vous devez donc mettre "espace" entre crochets et variable / valeur.

Neven
la source
non, je suppose, car comme j'ai demandé au script de reculer de deux jours lorsque le script s'exécute au début de deux jours de l'année et également de vérifier les premier et deuxième jours de chaque mois et de reculer de deux jours signifie ici si [$ month = "01"] && [$ day = "01"] nous supposons que le mois "01" et le premier jour "01" correspondent, passer à alors ou passer à la condition else
Kumar1
1
@AshokSanganahalli: Je ne sais pas comment cela est lié, mais votre condition IF ne fonctionne pas car vous n'avez pas "d'espace vide" entre crochets et valeur
Neven
@AshokSanganahalli Ce n'est généralement pas une bonne idée pour les personnes de votre niveau de contester les corrections de personnes ayant manifestement une meilleure compréhension sans au moins essayer l'indice. Si vos suppositions avaient raison, vous n'auriez pas à demander ici, n'est-ce pas?
Hauke ​​Laging
4
-1 pour les variables non citées et l'utilisation de ==au lieu de standard =.
Stéphane Chazelas
2
La question n'est pas taguée bash. L'opérateur de comparaison d'égalité dans la commande aka standard[test est =. [si pour les tests, il ne fait aucune affectation, il n'est donc pas nécessaire de lever l'ambiguïté. Certaines [implémentations prennent ==en charge une extension par rapport à la norme, mais pas toutes. Le shell de Bourne ash, poshle [s ou le /bin/[de certains systèmes par exemple ne le font pas. ==a été ajouté par ksh, je suppose pour la cohérence avec le même opérateur dans sa nouvelle (( ... ))construction (qui a à la fois = et ==, mais il n'a pas de standard)
Stéphane Chazelas