Hur man arbetar med variabler i Bash

By rik

Om du vill skapa egna skript och verkligen förstå koden som du kopierar in från nätet, är variabler ett måste. Vi ska nu utforska hur de fungerar!

Grunderna i variabler

Variabler är symboliska namn som representerar antingen textsträngar eller numeriska värden. När de används i kommandon och uttryck, tolkas de som om du hade skrivit det faktiska värdet som variabeln lagrar, istället för själva variabelnamnet.

För att skapa en variabel, ger du den ett namn och ett värde. Namnen ska vara beskrivande så att du enkelt minns vilket värde de representerar. Ett variabelnamn får inte börja med en siffra eller innehålla mellanslag, men det kan börja med ett understreck. I övrigt kan du använda en kombination av stora och små bokstäver och siffror.

Exempel på variabler

Låt oss skapa fem olika variabler. Syntaxen är enkel: först variabelns namn, sedan likhetstecknet = och därefter värdet. Tänk på att det inte får finnas något mellanrum före eller efter likhetstecknet. Att ge en variabel ett värde kallas ofta för att *tilldela* ett värde till variabeln.

Vi skapar fyra variabler med textsträngar och en numerisk variabel:

mitt_namn=Anna
min_favorit=Programmering
hans_namn=Olle
hans_favorit=Schack
ar=2024

För att visa värdet som lagras i en variabel, kan du använda kommandot `echo`. När du refererar till en variabel måste du skriva ett dollartecken `$` före variabelnamnet, som i exemplen nedan:

echo $mitt_namn
echo $min_favorit
echo $ar

Nu ska vi använda alla våra variabler på en gång:

echo "$min_favorit är för $mitt_namn som $hans_favorit är för $hans_namn (c) $ar"

Variablernas värden ersätter deras namn i utskriften. Du kan när som helst ändra värdet på en variabel. Om du vill ge `min_favorit` ett nytt värde, skriver du bara en ny tilldelning:

min_favorit=Fotboll

Om du kör kommandot igen får du nu ett annat resultat:

echo "$min_favorit är för $mitt_namn som $hans_favorit är för $hans_namn (c) $ar"

Samma kommando kan alltså ge olika resultat beroende på vilka värden som finns i variablerna.

Vi kommer att prata mer om citattecken senare. Här är några grundregler att hålla i minnet:

  • En variabel inuti enkla citattecken `’` tolkas som en bokstavlig text, inte som en variabel.
  • Variabler inuti dubbla citattecken `”` tolkas som variabler.
  • För att få fram värdet som lagras i en variabel, måste du använda ett dollartecken `$`.
  • En variabel utan ett dollartecken `$`, refererar till variabelnamnet.

Du kan också skapa variabler som får sina värden från andra variabler. Följande kommando skapar en ny variabel som heter `arets_tema` och den får sitt värde från en kombination av `min_favorit` och `ar`:

arets_tema="$min_favorit $ar"
echo $arets_tema

Variabler i skript

Variabler är oumbärliga för att skriva flexibla skript. De gör att ett skript kan vara generellt snarare än specifikt. För att illustrera skillnaden ska vi se på ett skript som räknar antalet filer i katalogen `/dev`.

Skriv in följande i en textfil och spara filen som `fil_antal.sh`:

#!/bin/bash

katalog_att_rakna=/dev

antal_filer=$(ls $katalog_att_rakna | wc -l)

echo $antal_filer filer i $katalog_att_rakna

Innan du kan köra skriptet, måste du ge det körrättigheter:

chmod +x fil_antal.sh

Du kör skriptet genom att skriva:

./fil_antal.sh

Detta skript skriver ut antalet filer i katalogen `/dev`. Så här fungerar det:

  • En variabel som heter `katalog_att_rakna` definieras och den tilldelas textsträngen `/dev`.
  • En annan variabel, `antal_filer` definieras. Denna variabel får sitt värde genom en kommandosubstitution. Det är kommandot inuti parenteserna `$( )`. Lägg märke till dollartecknet `$` före den första parentesen. Denna konstruktion utvärderar kommandot inuti parenteserna och ger tillbaka slutresultatet. I det här fallet tilldelas resultatet variabeln `antal_filer`.
  • Kommandot inuti `$( )` listar alla filer och kataloger (`ls`) i katalogen som finns i variabeln `katalog_att_rakna`, som är `/dev`.
  • Utmatningen från `ls` skickas vidare till kommandot `wc`. Option `-l` (radantal) gör att `wc` räknar antalet rader i utmatningen från kommandot `ls`. Eftersom varje fil skrivs ut på en egen rad, får vi antalet filer och underkataloger i katalogen `/dev`. Resultatet av detta tilldelas sedan till variabeln `antal_filer`.
  • Slutligen använder vi `echo` för att skriva ut resultatet.

Men detta fungerar bara för katalogen `/dev`. Hur kan vi få skriptet att fungera med vilken katalog som helst? Allt som behövs är en liten justering.

Använda kommandoradsparametrar i skript

Många kommandon, som `ls` och `wc`, tar emot kommandoradsparametrar. Dessa ger information till kommandot, så att det vet vad du vill att det ska göra. Om du vill att `ls` ska visa innehållet i din hemkatalog och även visa dolda filer, kan du använda följande kommando, där `~` (hemkatalog) och `-a` (alla) är kommandoradsparametrar:

ls ~ -a

Våra skript kan också ta emot kommandoradsparametrar. De refereras till som `$1` för den första parametern, `$2` för den andra, och så vidare upp till `$9` för den nionde parametern. Det finns också `$0`, som alltid innehåller namnet på själva skriptet.

Du kan referera till kommandoradsparametrar på samma sätt som andra variabler i skriptet. Låt oss ändra vårt skript och spara den nya versionen som `fil_antal2.sh`:

#!/bin/bash

katalog_att_rakna=$1

antal_filer=$(ls $katalog_att_rakna | wc -l)

echo $antal_filer filer i $katalog_att_rakna

Den här gången tilldelas variabeln `katalog_att_rakna` värdet från den första kommandoradsparametern, `$1`.

Resten av skriptet fungerar som tidigare. Men istället för att bara fungera med katalogen `/dev`, är det nu en generell lösning. Du kan använda det med vilken katalog som helst.

Gör skriptet körbart:

chmod +x fil_antal2.sh

Prova att köra skriptet med lite olika kataloger. Du kan börja med `/dev` för att se att du får samma resultat som tidigare:

./fil_antal2.sh /dev
./fil_antal2.sh /etc
./fil_antal2.sh /bin

Du får samma resultat (207 filer) som tidigare för katalogen `/dev`. Detta är som förväntat. Du får sedan katalogs-specifika resultat för de andra katalogerna.

För att förenkla skriptet, kan vi ta bort variabeln `katalog_att_rakna` helt och hållet och bara referera till `$1` direkt:

#!/bin/bash

antal_filer=$(ls $1 | wc -l)

echo $antal_filer filer i $1

Specialvariabler

Vi nämnde `$0`, som alltid innehåller skriptets filnamn. Detta gör att skriptet kan använda sitt eget namn i utskriften, även om det har bytt namn. Det är användbart i loggningssammanhang där du vill veta namnet på skriptet som lägger till en post.

Här är några andra specialvariabler som Bash har fördefinierat:

  • `$#`: Antalet kommandoradsparametrar som skickades till skriptet.
  • `$*`: Alla kommandoradsparametrar skickade till skriptet som en enda sträng.
  • `$@`: Alla kommandoradsparametrar skickade till skriptet som separata argument.
  • `$?:` Utgångsstatus från den senast körda processen.
  • `$$`: Process-ID (PID) för det aktuella skriptet.
  • `$USER`: Användarnamnet för den användare som kör skriptet.
  • `$HOSTNAME`: Datorns värdnamn där skriptet körs.
  • `$SECONDS`: Antalet sekunder som skriptet har körts.
  • `$RANDOM`: Ger ett slumpmässigt tal.
  • `$LINENO`: Skriptets aktuella radnummer.

Vi kan se hur de fungerar genom att skapa ett skript. Spara följande som en textfil med namnet `special.sh`:

#!/bin/bash

echo "Antal kommandoradsparametrar: $#"
echo "Parametrarna är: $@"
echo "Den första parametern är: $1"
echo "Skriptets namn: $0"
# Utför ett kommando för att kunna rapportera statusen
pwd
echo "pwd gav status: $?"
echo "Skriptets process-ID: $$"
echo "Skriptet körs av: $USER"
echo "Skriptet körs på: $HOSTNAME"
sleep 3
echo "Skriptet har körts i $SECONDS sekunder"
echo "Slumptal: $RANDOM"
echo "Aktuell radnummer i skriptet: $LINENO"

Gör skriptet körbart:

chmod +x special.sh

Nu kan du köra det med lite olika kommandoradsparametrar:

Miljövariabler

Bash använder miljövariabler för att definiera egenskaperna i den miljö som skapas när den startas. De lagrar information som Bash kan komma åt, som ditt användarnamn, din lokalisering, antalet kommandon i historiken, din standardredigerare och mycket mer.

För att se de aktuella miljövariablerna, använd följande kommando:

env | less

Genom att bläddra igenom listan kan du hitta variabler som är användbara i dina skript.

Exportera variabler

När ett skript körs, sker det i en egen process. Variablerna som skriptet använder är inte synliga utanför den processen. Om du vill att ett annat skript som körs från ditt skript, ska ha tillgång till en variabel, måste du exportera den. Vi visar hur du gör med hjälp av två skript.

Spara först följande med filnamnet `skript_ett.sh`:

#!/bin/bash

forsta_var=alpha
andra_var=bravo

# Kontrollera värdena
echo "$0: forsta_var=$forsta_var, andra_var=$andra_var"

export forsta_var
export andra_var

./skript_tva.sh

# Kontrollera värdena igen
echo "$0: forsta_var=$forsta_var, andra_var=$andra_var"

Detta skript skapar två variabler, `forsta_var` och `andra_var` och tilldelar dem värden. Sedan skriver det ut deras värden, exporterar variablerna och anropar `skript_tva.sh`. När `skript_tva.sh` avslutas, och kontrollen återgår till detta skript, skrivs variablerna ut igen. Då ser vi om de har ändrats.

Det andra skriptet som vi ska använda är `skript_tva.sh`. Det är detta skript som `skript_ett.sh` anropar. Skriv följande:

#!/bin/bash

# Kontrollera värdena
echo "$0: forsta_var=$forsta_var, andra_var=$andra_var"

# Tilldela nya värden
forsta_var=charlie
andra_var=delta

# Kontrollera värdena igen
echo "$0: forsta_var=$forsta_var, andra_var=$andra_var"

Detta andra skript skriver ut variablernas värden, ger dem sedan nya värden och skriver ut dem igen.

För att köra skripten, måste du ge dem körrättigheter:

chmod +x skript_ett.sh
chmod +x skript_tva.sh

Starta `skript_ett.sh` genom att skriva:

./skript_ett.sh

Detta är vad utskriften säger oss:

  • `skript_ett.sh` skriver ut variablernas värden, som är alpha och bravo.
  • `skript_tva.sh` skriver ut variablernas värden (alpha och bravo), som den har fått från det första skriptet.
  • `skript_tva.sh` ändrar variablerna till charlie och delta.
  • `skript_ett.sh` skriver sedan ut variablernas värden, som fortfarande är alpha och bravo.

Det som händer i det andra skriptet, stannar i det andra skriptet. Det är som att kopior av variablerna skickas till det andra skriptet, men de försvinner när det skriptet är klart. De ursprungliga variablerna i det första skriptet påverkas inte av vad som händer med kopiorna i det andra skriptet.

Citattecken runt variabler

Du kanske har märkt att skript ofta sätter variabler inom dubbla citattecken `”` när de refererar till dem. Det gör att variablerna tolkas korrekt och deras värden används när raden exekveras i skriptet.

Om värdet du tilldelar en variabel innehåller mellanslag, måste dessa inkluderas i citattecken. Det beror på att Bash i standardutförande tolkar mellanslag som separatorer.

Här är ett exempel:

webbplats=Min Hemsida

Bash tolkar mellanslaget framför ”Hemsida” som ett kommando. Den rapporterar att det inte finns något kommando ”Hemsida” och ignorerar resten av raden. `echo` visar att variabeln `webbplats` inte har något värde.

Försök igen med citattecken runt värdet:

webbplats="Min Hemsida"

Den här gången tolkas allt som ett enda värde och tilldelas variabeln `webbplats`.

`echo` är din vän

Det kan ta lite tid att vänja sig vid kommandosubstitution, citattecken och att komma ihåg när man ska använda dollartecken.

Innan du trycker på Enter för att utföra ett kommando, testa det med `echo` först. Då kan du se att det som kommer att hända är det som du önskar. Du kan också fånga upp misstag i syntaxen.