Om man använder kommandot shift i ett
Bashprogram, så tas det första
argumentet bort.
Det som förut var $2 blir då $1,
det som var $3 blir $2 osv.
Samtidigt minskar $# med ett.
Kommandot shift 2 har samma verkan som två stycken
shift. Dvs $# minskar med två,
det som var $3 blir $1,
det som var $4 blir $2 osv.
På motsvarande sätt fungerar shift 3,
shift 4 osv.
Följande program, som helt enkelt anger alla sina argument, ger ett exempel på hur shift kan användas.
#!/bin/bash echo "Totalt $# argument." while [ $# -gt 0 ] do echo "Ett argument är $1." shift done
Genom att köra programmet ovan några gånger ska
vi demonstrera hur Bash hanterar argumenten.
Vi minns sedan avsnitt 3.4
att oskyddade blank- och nyradtecken separerar argument.$ allaargument ole 'dole doff'
Totalt 2 argument.
Ett argument är ole.
Ett argument är dole doff.
$ allaargument "Hej och hå"
Totalt 1 argument.
Ett argument är Hej och hå.
$ Med hjälp av citationstecken kan man till och med
ange den tomma textsträngen som ett argument.$ allaargument Ett tomt "" argument
Totalt 4 argument.
Ett argument är Ett.
Ett argument är tomt.
Ett argument är .
Ett argument är argument.
$ Separationen av argument sker efter eventuella
omskrivningar (med undantag för jokeromskrivningar):$ NAMN="Göran Andersson"
$ allaargument namnet är $NAMN
Totalt 4 argument.
Ett argument är namnet.
Ett argument är är.
Ett argument är Göran.
Ett argument är Andersson.
$ Ovan skrevs $NAMN om till Göran Andersson,
vilket räknas som två skilda argument.
Om variabeln namn inte har getts något värde, så
skrivs $namn om till en tom textsträng.
Därför räknas $ODEFINIERAD som
noll argument i följande exempel:$ allaargument Värdet är $ODEFINIERAD
Totalt 2 argument.
Ett argument är Värdet.
Ett argument är är.
$Ibland är detta tvärtemot vad man vill.
Hur får man Bash att uppfatta uttrycket
$variabel som exakt ett argument
även efter omskrivningen? Genom att
omge det med citationstecken!$ allaargument namnet är "$NAMN"
Totalt 3 argument.
Ett argument är namnet.
Ett argument är är.
Ett argument är Göran Andersson.
$ allaargument Värdet är "$ODEFINIERAD"
Totalt 3 argument.
Ett argument är Värdet.
Ett argument är är.
Ett argument är .
$
Om man slarvar vid hanteringen av argument, så kan man råka ut för märkliga spratt. Betrakta tex följande program, leta2:
#!/bin/bash if grep -q $1 $2 ; then echo 'Ja, texten finns i filen.' else echo 'Nej, texten finns inte i filen.' fi
Det första argumentet ska vara en text, det andra ett filnamn. Programmet har till uppgift att ta reda på om texten finns i den angivna filen. Vi har gett grep flaggan -q för att slippa dess utskrift. Antag att filen textfil har följande innehåll:
Det första argumentet ska vara en text, det andra ett filnamn. Programmet har till uppgift att ta reda på om texten finns i den angivna filen.Så här kan det gå när vi kör programmet leta2:$ leta2 'finns inte' textfil
För att rätta till felet måste vi se till att
grep betraktar värdet av $1 som
exakt ett ord. Vi omger därför $1
med citationstecken.
Hur går det om det andra argumentet, filnamnet,
innehåller ett mellanslag? Dåligt. Värdet av $2
betraktas då av grep som flera filnamn,
och programmet gör fel.
Så här ska det se ut i stället:$ cat leta3
#!/bin/bash
if grep -q "$1" "$2" ; then
echo 'Ja, texten finns i filen.'
else
echo 'Nej, texten finns inte i filen.'
fi
$ cp textfil 'konstig fil'
$ leta3 finns 'konstig fil'
Ja, texten finns i filen.
$ leta3 'finns inte' 'konstig fil'
Nej, texten finns inte i filen.
$
Antag nu att vi vill skriva om leta3
så att det kan söka efter en viss text i
flera olika filer. Dvs det första argumentet
ska vara söktexten, de övriga ska vara filnamn.
Då ska grep-kommandot ändras till
grep -q "$1" "$2" "$3" ifall man anger två filnamn,
till grep -q "$1" "$2" "$3" "$4" ifall man anger tre
osv. Hur ska det gå till när vi inte vet hur många
argumenten är?
Bash tolkar $* som
$1 $2 $3 osv fram till sista argumentet,
men det duger inte här eftersom argumenten
kan innehålla mellanslag.
Istället ska vi använda parametern @.
Den har samma värde som * utom när den
omges av citationstecken:
"$@" tolkas som
"$1" "$2" "$3" osv, vilket är just vad
vi behöver. Kommandot ska alltså skrivas
grep -q "$@".
Vi använder följande program för att belysa diskussionen ovan:
#!/bin/bash echo "Jag fick $# argument, men..." allaargument $* allaargument "$*" allaargument "$@"
Så här går det när vi kör programmet:$ argumenttest ole 'dole doff'
Jag fick 2 argument, men...
Totalt 3 argument.
Ett argument är ole.
Ett argument är dole.
Ett argument är doff.
Totalt 1 argument.
Ett argument är ole dole doff.
Totalt 2 argument.
Ett argument är ole.
Ett argument är dole doff.
$Programmet
allaargument anropades tre gånger.
Varje gång vidarebefordrades argumenten,
fast det skedde på olika sätt.
Först vidarebefordrades de som
ole dole doff (allaargument
fick då tre argument), sedan som
"ole dole doff" (allaargument
fick då ett argument) och till sist som
"ole" "dole doff" (vilket gav
två argument).
Det är bara "$@" som bevarar argumenten
precis som de var.
Man kan inte ge tex parametern 1 ett nytt värde genom en direkt tilldelning som om det varit en vanlig variabel. Däremot kan ett program ge sig själv de nya argumenten argument med kommandot set argument. Följande program använder set:
#!/bin/bash allaargument "$@" set Många "nya, fina" argument allaargument "$@"
Låt oss prova programmet!$ argumenttest2 hejsan svejsan
Totalt 2 argument.
Ett argument är hejsan.
Ett argument är svejsan.
Totalt 3 argument.
Ett argument är Många.
Ett argument är nya, fina.
Ett argument är argument.
$
Programmet filinformation nedan använder set på ett intressantare sätt:
#!/bin/bash set $(wc "$1") echo "Filen $4 har $1 rader och är $3 byte lång."
Som argument ska man ange ett filnamn.
Programmet talar om hur många rader och tecken
filen innehåller.$ wc /etc/passwd
30 42 1291 /etc/passwd
$ filinformation /etc/passwd
Filen /etc/passwd har 30 rader och är 1291 byte lång.
$ Utskriften från wc $1 har fyra delar:
först antal rader, sedan antal ord respektive tecken
och till sist filnamnet. Dessa fyra delar sätts
som argument, så att de kan plockas ut med
$1, $2 osv.