set -u-användning fungerar inte som förväntat

Jag lär mig hur man effektivt använder olika set alternativ i mitt skript och stötte på set -u som verkar vara perfekt för att avsluta mitt skript om en variabel inte blir korrekt inställd (t.ex. att radera användare). Enligt man sida, set -u och set -e gör följande …

-e Exit immediately if a command exits with a non-zero status. -u Treat unset variables as an error when substituting. 

Jag skapade ett testskript för att testa denna funktion, men det verkar inte fungera som förväntat . Kanske kan någon bättre förklara min fråga för mig och var jag tolkar fel? Testmanus finns nedan. Tack.

set -e set -u testing="This works" echo $? echo ${testing} testing2= echo $? echo ${testing2} testing3="This should not appear" echo $? echo ${testing3} 

Jag förväntar mig att skriptet visar 0 och ”Detta fungerar” , och misslyckas sedan som ${testing2} inte inställd.

Istället visas 0 och ”Detta fungerar” , följ av 0 och sedan 0 Detta ska inte visas

Kan någon ge lite kunskap? Tack.

Kommentarer

  • Så uppföljning … finns det något sätt att göra inställningen av en variabel till nullsträngen olaglig / höja ett fel? Jag ' jag gissar inte.

Svar

Från ” man Bash ”:

En parameter ställs in om den har tilldelats ett värde. Nollsträngen är ett giltigt värde. När en variabel väl har ställts in kan den endast avaktiveras med kommandot unset inbyggt.

När du gör testing2= du ställer in variabeln till nollsträngen.

Ändra den till unset testing2 och försök igen.


set -e hjälper inte i det här fallet eftersom en uppgift aldrig har en utgångskod på 1. Testa detta för att se att det senast utförda kommandot (tilldelningen) har en utgångskod på 0 eller läs den här frågan :

$ false; a=""; echo $? 0 

Och jag tror också att användningen av set -e är mer ett problem som en lösning.

Vad som kan få ett fel med användningen av unset-variabler är set -u:

#!/bin/bash set -u testing="This works" echo ${testing} unset testing2 echo ${testing2} testing3="This should not appear" echo ${testing3} 

Kommer att matas ut:

$ ./script.sh This works ./script.sh: line 9: testing2: unbound variable 

Svar

testing2= ställer variabeln testing2 till en tom sträng; variabeln är faktiskt inställd .

Men om du skulle köra echo $testing99 i ett interaktivt Bash-skal (utan att ställa in errexit, dvs. set -e), skulle du få ett fel:

bash: testing99: unbound variable 

Bortsett från

När jag testade skript just nu upptäckte jag att ett interaktivt skal inte alltid går ut när du försöker expandera en variabel som inte har ställts in medan ett icke-interaktivt skal (kör ett skalskript) lämnar alltid . Enligt POSIX-mansidan för set:

-u Skalet ska skriva ett meddelande till standardfel när den försöker expandera en variabel som inte är inställd och omedelbart avsluta. Ett interaktivt skal ska inte avslutas.

Ett interaktivt Bash-skal kommer inte att avslutas om inte errexit har också har ställts in. Å andra sidan kommer ett interaktivt bindeskal inte att avslutas – även om set -e tidigare har körts.

Kommentarer

  • Om bindestreck inte avslutas med set -e; set -u; unset aa; echo $ aa, då är dash fel.
  • @schily När jag först märkte detta, tänkte jag att dash-författarna visste bättre än mig och att det kan ha varit en viss tvetydighet i POSIX-specifikationerna men att ha markerad pubs.opengroup.org/onlinepubs/9699919799/utilities/… , jag håller med om att det ser ut som ett fel, okej.
  • Det finns en enkel regel: när både Korn Shell och Bourne Shell är överens och en annan skalimplementering har en avvikelse, så fungerar det andra skalet felaktigt.

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *