Det är inte svårt att skicka text som indata till ett program.
Man kan helt enkelt låta echo skriva ut texten
till programmet via en rörledning. Men det finns ett annat
sätt, som ibland är bekvämare, nämligen att
omdirigera indatan med tecknen <<.
I följande exempel
skickar vi texten Eva Thulin som indata till programmet
hej från sida
:$ hej <<EOF
> Eva Thulin
> EOF
Hej, Eva Thulin!
$Efter tecknen << skriver man ett godtyckligt ord.
Ofta väljer man EOF, som står för ''End Of File''.
Därefter skriver man den text som ska utgöra kommandots indata.
Man avslutar med att på en ny rad skriva samma ord som man
skrev efter tecknen <<.
På detta sätt kan indatan till ett kommando skrivas
i anslutning till själva kommandot.
#!/bin/bash
TAL=10
cat <<- EOF
Hej, $1!
Idag är det den $(date).
Visste du att $TAL/2=$((TAL/2))?
Hejdå!
EOF
Programmet hejsan ovan skriver ut fyra rader text
med hjälp av cat.
För att göra programmet lättläst har vi satt ett
tabulatorsteg före varje rad av texten.
Minustecknet efter tecknen << är en signal till skalet
att dessa tabulatorsteg ska tas bort innan texten skickas genom
cat.$ hejsan
Hej, Göran!
Idag är det den sön feb 22 19:01:17 CET 1998.
Visste du att 10/2=5?
Hejdå!
$Körningen ovan visar att några av de vanliga
omskrivningarna kan användas i den text som
omdirigeras med <<. Om man beskyddar
någon del av ordet efter <<, så undviker
skalet dessa omskrivningar.
#!/bin/bash
cat <<- 'EOF'
Hej, $1!
Idag är det den $(date).
EOF
Programmet ovan ger följande utskrift:$ hejsan
Hej, $1!
Idag är det den $(date).
$
Man kan koppla samman ett antal kommandon genom
att låta dem omges av parenteser. Därigenom
får kommandona en gemensam in- och utdata.
Betrakta tex följande två kommandon:$ echo -n 'Dagens datum är ' ; date
Dagens datum är sön feb 22 19:18:57 CET 1998
$Om vi vill skicka utskriften från dessa kommandon genom
wc, så kan vi inte göra så här:$ echo -n 'Dagens datum är ' ; date | wc
Dagens datum är 1 6 29
$Vad som hände var att bara det sista kommandots utdata skickades till
wc. Bash prioriterar nämligen operatorn |
högre än ;. Med hjälp av parenteser går det bättre:$ (echo -n 'Dagens datum är ' ; date) | wc
1 9 45
$Kommandon som kopplats samman med hjälp av parenteser
exekveras i ett subskal. Detta innebär att eventuella
förändringar av variabelvärden eller nuvarande katalog mellan
parenteserna inte är bevarade efter att
kommandona kört färdigt.
Om man vill att kommandona ska köras i det nuvarande
skalet i stället för i ett subskal, så ska man använda
klamrar i stället för parenteser; det sista kommandot
måste då avslutas med ett semikolon.$ pwd
/home/göran/dikter
$ ( cd /etc ; ls -l passwd )
-rw-r--r-- 1 root root 1291 nov 25 14:37 passwd
$ pwd
/home/göran/dikter
$ { cd /tmp ; ls ; }
emacs.gz
$ pwd
/tmp
$ Ändringen av den nuvarande katalogen skedde
i ett subskal i det första exemplet,
och då bevarades inte ändringen.
Den andra gången bevarades dock ändringen.
Ett annat skäl att koppla samman kommandon så här är
att de då kan köras efter varandra i bakgrunden.
Nedan startar vi två jobb i bakgrunden;
det första väntar i 30 sekunder och skriver därefter ut
vilka filer som finns i den nuvarande katalogen, medan det
andra dekomprimerar filen emacs.gz.$ (sleep 30 ; ls ) &
[1] 7842
$ gunzip emacs.gz &
[2] 7844
$ jobs
[1]- Running ( sleep 30; ls -NF --color ) &
[2]+ Running gunzip emacs.gz &
$ echo Nu emacs*
är det klart
Nu är det klart
[1]- Done ( sleep 30; ls -NF --color )
[2]+ Done gunzip emacs.gz
$Vid kommandot jobs ovan ser man att de båda jobben är
i full gång. Men medan jag skrev in nästa kommando, kom utskriften
av ls från första jobbet emellan. Obekymrad om detta fullbordade
jag mitt kommando,
echo Nu är det klart. Innan nästa prompt skrevs ut gav Bash
besked om att de båda jobben var klara.
(Faktum är att jobb nummer två måste ha blivit klart före
jobb nummer 1 eftersom ls inte skrev ut emacs.gz.)