Hur man arbetar med variabler i Bash

Variabler är viktiga om du vill skriva skript och förstå vad den koden du ska klippa och klistra in från webben kommer att göra med din Linux-dator. Vi kommer igång!

Variabler 101

Variabler är namngivna symboler som representerar antingen en sträng eller ett numeriskt värde. När du använder dem i kommandon och uttryck, behandlas de som om du hade skrivit värdet de har istället för variabelns namn.

För att skapa en variabel anger du bara ett namn och ett värde för den. Dina variabelnamn ska vara beskrivande och påminna dig om värdet de har. Ett variabelnamn kan inte börja med ett tal, och det får inte heller innehålla mellanslag. Det kan dock börja med ett understreck. Förutom det kan du använda valfri blandning av stora och små alfanumeriska tecken.

Exempel

Här skapar vi fem variabler. Formatet är att skriva namnet, likhetstecknet = och värdet. Observera att det inte finns ett mellanslag före eller efter likhetstecknet. Att ge en variabel ett värde kallas ofta för att tilldela variabeln ett värde.

Vi skapar fyra strängvariabler och en numerisk variabel, this_year:

me=Dave
my_boost=Linux
him=Popeye
his_boost=Spinach
this_year=2019

Till se värdet hålls i en variabel, använd kommandot echo. Du måste föregå variabelnamnet med ett dollartecken $ när du refererar till värdet den innehåller, som visas nedan:

echo $my_name
echo $my_boost
echo $this_year

De

Låt oss använda alla våra variabler på en gång:

echo "$my_boost is to $me as $his_boost is to $him (c) $this_year"

De

Variablernas värden ersätter deras namn. Du kan också ändra värdena på variabler. För att tilldela ett nytt värde till variabeln, my_boost, upprepar du bara vad du gjorde när du tilldelade dess första värde, så här:

my_boost=Tequila

De

Om du kör om det föregående kommandot får du nu ett annat resultat:

echo "$my_boost is to $me as $his_boost is to $him (c) $this_year"

Ekot

Så du kan använda samma kommando som refererar till samma variabler och få olika resultat om du ändrar värdena i variablerna.

Vi kommer att prata om att citera variabler senare. För nu, här är några saker att komma ihåg:

En variabel i enkla citattecken ’ behandlas som en bokstavlig sträng och inte som en variabel.
Variabler inom citattecken ” behandlas som variabler.
För att få värdet kvar i en variabel måste du ange dollartecknet $.
En variabel utan dollartecken $ ger bara namnet på variabeln.

Du kan också skapa en variabel som tar sitt värde från en befintlig variabel eller ett antal variabler. Följande kommando definierar en ny variabel som heter drink_of_the_Year och tilldelar den de kombinerade värdena för variablerna my_boost och this_year:

drink_of-the_Year="$my_boost $this_year"
echo drink_of_the-Year

Årets_drink=

Hur man använder variabler i skript

Skript skulle vara helt försämrade utan variabler. Variabler ger den flexibilitet som gör ett skript till en generell, snarare än en specifik, lösning. För att illustrera skillnaden, här är ett skript som räknar filerna i /dev-katalogen.

Skriv in detta i en textfil och spara det sedan som fcnt.sh (för ”filantal”):

#!/bin/bash

folder_to_count=/dev

file_count=$(ls $folder_to_count | wc -l)

echo $file_count files in $folder_to_count

Innan du kan köra skriptet måste du göra det körbart, som visas nedan:

chmod +x fcnt.sh

Skriv följande för att köra skriptet:

./fcnt.sh

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

En variabel som heter folder_to_count är definierad och den är inställd för att hålla strängen ”/dev.”
En annan variabel, kallad file_count, definieras. Denna variabel tar sitt värde från en kommandosubstitution. Detta är kommandofrasen mellan parentesen $( ). Observera att det finns ett dollartecken $ före den första parentesen. Denna konstruktion $( ) utvärderar kommandona inom parentes och returnerar sedan deras slutvärde. I det här exemplet tilldelas det värdet till variabeln file_count. När det gäller variabeln file_count har den skickat ett värde att hålla; det handlar inte om hur värdet erhölls.
Kommandot som utvärderas i kommandosubstitutionen utför en ls-fillista i katalogen i variabeln folder_to_count, som har satts till ”/dev.” Så, skriptet kör kommandot ”ls /dev.”
Utdata från detta kommando överförs till wc-kommandot. Alternativet -l (radantal) får wc att räkna antalet rader i utgången från kommandot ls. Eftersom varje fil är listad på en separat rad, är detta antalet filer och underkataloger i katalogen ”/dev”. Detta värde tilldelas variabeln file_count.
Den sista raden använder eko för att mata ut resultatet.

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

Hur man använder kommandoradsparametrar i skript

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

ls ~ -a

Våra skript kan acceptera kommandoradsparametrar. De hänvisas till som $1 för den första parametern, $2 som den andra, och så vidare, upp till $9 för den nionde parametern. (Faktiskt finns det en $0 också, men den är reserverad för att alltid hålla manuset.)

Du kan referera till kommandoradsparametrar i ett skript precis som vanliga variabler. Låt oss ändra vårt skript, som visas nedan, och spara det med det nya namnet fcnt2.sh:

#!/bin/bash

folder_to_count=$1

file_count=$(ls $folder_to_count | wc -l)

echo $file_count files in $folder_to_count

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

Resten av manuset fungerar precis som det gjorde tidigare. Snarare än en specifik lösning är ditt skript nu ett allmänt. Du kan använda den i vilken katalog som helst eftersom den inte är hårdkodad för att bara fungera med ”/dev.”

Så här gör du skriptet körbart:

chmod +x fcnt2.sh

Nu, prova det med några kataloger. Du kan göra ”/dev” först för att se till att du får samma resultat som tidigare. Skriv följande:

./fnct2.sh /dev
./fnct2.sh /etc
./fnct2.sh /bin

Du får samma resultat (207 filer) som tidigare för ”/dev”-katalogen. Detta är uppmuntrande, och du får katalogspecifika resultat för var och en av de andra kommandoradsparametrarna.

För att förkorta skriptet kan du avstå från variabeln folder_to_count helt och hållet och bara referera till $1 genomgående, enligt följande:

#!/bin/bash 

file_count=$(ls $1  wc -l) 

echo $file_count files in $1

Arbeta med specialvariabler

Vi nämnde $0, som alltid är inställt på filnamnet för skriptet. Detta gör att du kan använda skriptet för att göra saker som att skriva ut dess namn korrekt, även om det har bytt namn. Detta är användbart i loggningssituationer, där du vill veta namnet på processen som lade till en post.

Följande är de andra speciella förinställda variablerna:

$#: Hur många kommandoradsparametrar skickades till skriptet.
[email protected]: Alla kommandoradsparametrar skickas till skriptet.
$?: Utgångsstatus för den senaste processen som körs.
$$: Process ID (PID) för det aktuella skriptet.
$USER: Användarnamnet för användaren som kör skriptet.
$HOSTNAME: Värdnamnet på datorn som kör skriptet.
$SECONDS: Antalet sekunder som skriptet har körts i.
$RANDOM: Returnerar ett slumpmässigt tal.
$LINENO: Returnerar skriptets nuvarande radnummer.

Du vill se alla i ett manus, eller hur? Du kan! Spara följande som en textfil som heter special.sh:

#!/bin/bash

echo "There were $# command line parameters"
echo "They are: [email protected]"
echo "Parameter 1 is: $1"
echo "The script is called: $0"
# any old process so that we can report on the exit status
pwd
echo "pwd returned $?"
echo "This script has Process ID $$"
echo "The script was started by $USER"
echo "It is running on $HOSTNAME"
sleep 3
echo "It has been running for $SECONDS seconds"
echo "Random number: $RANDOM"
echo "This is line number $LINENO of the script"

Skriv följande för att göra det körbart:

chmod +x special.sh

Nu kan du köra det med en massa olika kommandoradsparametrar, som visas nedan.

Miljövariabler

Bash använder miljövariabler för att definiera och registrera egenskaperna för den miljö som den skapar när den startas. Dessa lagrar information som Bash lätt kan komma åt, såsom ditt användarnamn, lokalitet, antalet kommandon som din historikfil kan hålla, din standardredigerare och mycket mer.

För att se de aktiva miljövariablerna i din Bash-session, använd det här kommandot:

env | less

De

Om du bläddrar igenom listan kanske du hittar några som skulle vara användbara att referera till i dina skript.

Hur man exporterar variabler

När ett skript körs är det i sin egen process, och variablerna som det använder kan inte ses utanför den processen. Om du vill dela en variabel med ett annat skript som ditt skript lanserar, måste du exportera den variabeln. Vi visar dig hur du gör med två skript.

Spara först följande med filnamnet script_one.sh:

#!/bin/bash

first_var=alpha
second_var=bravo

# check their values
echo "$0: first_var=$first_var, second_var=$second_var"

export first_var
export second_var

./script_two.sh

# check their values again
echo "$0: first_var=$first_var, second_var=$second_var"

Detta skapar två variabler, first_var och second_var, och det tilldelar några värden. Den skriver ut dessa till terminalfönstret, exporterar variablerna och anropar script_two.sh. När script_two.sh avslutas, och processflödet återgår till det här skriptet, skrivs variablerna ut till terminalfönstret igen. Sedan kan du se om de ändrats.

Det andra skriptet vi kommer att använda är script_two.sh. Det här är skriptet som script_one.sh anropar. Skriv följande:

#!/bin/bash

# check their values
echo "$0: first_var=$first_var, second_var=$second_var"

# set new values
first_var=charlie
second_var=delta

# check their values again
echo "$0: first_var=$first_var, second_var=$second_var"

Detta andra skript skriver ut värdena för de två variablerna, tilldelar dem nya värden och skriver dem sedan ut igen.

För att köra dessa skript måste du skriva följande för att göra dem körbara:

chmod +x script_one.sh
chmod +x script_two.sh

Och skriv nu följande för att starta script_one.sh:

./script_one.sh

Detta är vad utgången säger oss:

script_one.sh skriver ut värdena för variablerna, som är alfa och bravo.
script_two.sh skriver ut värdena för variablerna (alfa och bravo) som det tog emot dem.
script_two.sh ändrar dem till charlie och delta.
script_one.sh skriver ut värdena för variablerna, som fortfarande är alfa och bravo.

Det som händer i det andra manuset stannar i det andra manuset. Det är som att kopior av variablerna skickas till det andra skriptet, men de kasseras när det skriptet avslutas. De ursprungliga variablerna i det första skriptet ändras inte av något som händer med kopiorna av dem i det andra.

Hur man citerar variabler

Du kanske har märkt att när skript refererar till variabler står de inom citattecken ”. Detta gör att variabler kan refereras korrekt, så deras värden används när raden exekveras i skriptet.

Om värdet du tilldelar en variabel innehåller mellanslag måste de stå inom citattecken när du tilldelar dem till variabeln. Detta beror på att Bash som standard använder ett mellanslag som avgränsare.

Här är ett exempel:

site_name=How-To Geek

Bash ser utrymmet före ”Geek” som en indikation på att ett nytt kommando börjar. Den rapporterar att det inte finns något sådant kommando och överger linjen. echo visar oss att variabeln site_name inte innehåller någonting – inte ens texten ”How-To”.

Försök igen med citattecken runt värdet, som visas nedan:

site_name="How-To Geek"

site_name=

Den här gången känns det igen som ett enda värde och tilldelas korrekt till variabeln site_name.

echo är din vän

Det kan ta lite tid att vänja sig vid att beordra substitution, citera variabler och komma ihåg när dollartecknet ska inkluderas.

Innan du trycker på Enter och utför en rad med Bash-kommandon, prova det med eko framför sig. På så sätt kan du se till att det som kommer att hända är vad du vill. Du kan också fånga eventuella misstag du kan ha gjort i syntaxen.