Funzioni e Sottoprocedure

Chiamare altre procedure

Ogni procedura con permesso di esecuzione è un comando Unix e può essere invocata da ogni altra procedura

Si applicano le normali considerazioni di percorsi e permessi

Le procedure chiamate sono eseguite da sottoshell

Tutte le loro variabili sono locali a loro

Se cambiano l'ambiente la procedura chiamante non lo sente

Per eseguire la procedura proc nella shell corrente:

. proc oppure
source proc

Funzioni

Una funzione è semplicemente una serie di istruzioni raggruppate e identificate da un nome

  • Le variabili della funzione sono di default globali
  • Non vi è un valore di ritorno

In realtà sono subroutines, non funzioni come concepite da altri linguaggi di programmazione.

Sintassi di definizione:

function funzione {
  istruzioni
}

Anche solo:

funzione() {
...
}

Invocate solo menzionandone il nome:

. . .
funzione
. . .

Le funzioni devono essere definite prima di essere invocate

Parametri

  • Le funzioni possono ricevere parametri
  • I parametri attuali sono semplici argomenti dell'invocazione della funzione
  • I parametri formali sono $1 $2 ecc.

Ritorno

  • La funzione ritorna dopo la }
  • Può tornare prima col comando return
  • Può settare uno stato di ritorno con return num

Convenzioni come con le procedure:

  • 0 - successo
  • >0 - fallimento

Il chiamante può testare $?

Esempio.

(funz1.sh)

#! /bin/bash
error(){
  echo "$1" >&2
  echo "$0: usage: $0 num" >&2
  exit $2
}
# main
(( $# < 1 )) && error "Argomenti mancanti" 3
(( $1 < 100 )) && error "Numero troppo piccolo" 250
echo "$1 e' un bel numero"

Notare che il main:

  • non ha nessuna etichetta particolare
    • non è una funzione
  • è l'ultimo codice del file
  • è una buona idea commentare l'inizio del main

I parametri formali del main sono diversi da quelli delle funzioni

Variabili locali

Variabili locali alla funzione sono dichiarate con la parola chiave local

Si può anche simulare un valore di ritorno

Esempio.

(funz2.sh)

#! /bin/bash
mult() {
  local risult=$(($1*$2))
  echo "$risult"
}
# main
ris=$(mult 3 5)
echo $ris

Il comando eval

Sintassi:

eval assegnazione

Esegue l'assegnazione due volte,
la seconda col risultato della prima

Esempio.

(eval1.sh)

#! /bin/bash
foo=10 bar=foo
x='$'$bar
echo "Senza eval: $x"
eval y='$'$bar
echo "Con eval: $y"

Uso:

./eval1.sh 
Senza eval: $foo
Con eval: 10

Notare che non si può scrivere $$bar poichè la shell tenterebbe di interpretarli entrambi. Occorre che il primo $ sia nascosto con '$'.

In presenza di quotes la shell ignora il contenuto, ma al contempo le toglie. Quindi quando valutata la seconda volta, y ha assegnato il valore $foo ovvero 10.

Altro esempio.

(eval2.sh)

#! /bin/bash
$( echo var=5 )
eval $( echo var=5 )
echo $var
a="ls * | sort"
$a
eval $a

Lancio:

./eval2.sh
./eval2.sh: line 2: var=5: command not found
5
ls: cannot access |: No such file or directory
ls: cannot access sort: No such file or directory
eval1.sh  eval2.sh ...
eval1.sh
eval2.sh
...

Il comando $( echo var=5 ) esegue echo var=5 che manda ad output la stringa var=5. Non è più un'assegnazione, è una stringa. Tenta poi di eseguire la stringa "var=5" e non trova nessun comando di quel nome.

Con eval invece legge la stringa var=5 come se fosse appena stata digitata da tastiera e la vede come assegnazione.

Con a="ls * | sort" la variabile a riceve una stringa. Non si può eseguire una stringa che contiene metacaratteri, deve essere riscandita dalla shell per comprendere e interpretare i metacaratteri. Altrimenti vengono visti come argomenti del comando.

Se fosse stato solo a="ls *" bastava per l'esecuzione, ma nel nostro caso | e sort sono visti come nome file argomenti di ls.

La parte ls * è ancora valida e viene eseguita, producendo un listato (orizzontale). I comandi completano anche parzialmente.

Se avessimo scritto a="ls *| sort" non avrebbe riconosciuto nemmeno il file *| e avrebbe fallito completamente.

Finalmente eval $a riscandisce la stringa "ls * | sort", la comprende e la esegue, producendo un listato verticale.

results matching ""

    No results matching ""