Esercizi di programmazione in shell

Transcript

Esercizi di programmazione in shell
Esercizi di programmazione in shell
- Gennaio 2004 –
Soluzioni
1. Scrivere uno script che riceve due parametri. Il primo indica un valore
numerico, il secondo un formato tra ottale (o), esadecimale (x) e notazione
scientifica (e). Lo script produce come risultato il valore numerico nel formato
richiesto.
Input: ./uno 9 -o
Output: 11
Script:
#!/bin/bash
if [
echo
exit
fi
case
-o)
-x)
-e)
*)
esac
$# -lt 2 ] ; then
"Usage: primo a_number format (format =o,x,e)" ;
1 ;
"$2" in
printf "%o\n" "$1" ;;
printf "%x\n" "$1" ;;
printf "%e\n" "$1" ;;
echo "ERROR: Unknown conversion, $2!" ;;
2. Si realizzi uno script bash che riceve due parametri. Il primo è una stringa
che rappresenta il nome di un comando. Lo script produce una lista con tutti i
processi che sono in esecuzione e sono stati lanciati da un comando il cui nome
contiene la stringa passata come parametro. La lista contiene i campi
normalmente prodotti dal comando ps. Il primo parametro (-h) è opzionale, e se
specificato indica che l'intestazione prodotta da ps deve essere stampata.
Input: ./due -h nautilus
Output:
UID
PID PPID C STIME TTY
steno
1050
1 0 Jan16 ?
steno
1108
1 0 Jan16 ?
steno
1110
1 0 Jan16 ?
steno
2325 1077 0 00:24 pts/0
TIME
00:00:08
00:00:00
00:00:01
00:00:00
CMD
nautilus --no-default-window --s
/usr/libexec/nautilus-throbber /usr/libexec/nautilus-text-view
/bin/bash ./due -h nautilus
Script:
#!/bin/bash
HEADER="false"
PSCMD="/bin/ps -ef"
case "$1" in
# sarà
usando case
-h) HEADER=true ; shift ;;
esac
possibile aggiungere altri parametri
if [ -z "$1" ] ; then
echo Usage: lspids [-h] process ;
exit 1;
fi
if [ "$HEADER" = "true" ] ; then
$PSCMD 2> /dev/null | head -n 1 ;
fi
$PSCMD 2> /dev/null | grep "$1" | grep -v grep
3. Scrivere un comando che ricevere in input una lista di file e stampa a video
un diagramma a barre in cui per ogni file è stampata una barra proporzionale
alla sua occupazione su disco in KByte.
Input: ./tre *
Output:
Cestino
due
due~
Eclipse.desktop
Home
script.txt
shellex.pdf
starthere.desktop
tre
tre~
uno
uno~
WebRatio.desktop
zip
= 4 KB
= 4 KB
= 4 KB
= 4 KB
= 4 KB
== 8 KB
========== 68 KB
= 4 KB
= 4 KB
= 4 KB
= 4 KB
= 4 KB
= 4 KB
= 4 KB
Script:
#!/bin/bash
du -hk "$@" > /tmp/$0$$.tmp
massimo=`cat /tmp/$0$$.tmp | awk 'BEGIN { max=0; } { if (max<$1) max=$1; } END {
printf("%d",max); }'`
maxlen=`cat /tmp/$0$$.tmp | awk 'BEGIN { max=0; } { if (max<length($2))
max=length($2); } END { printf("%d",max); }'`
cat /tmp/$0$$.tmp | awk -v MAXLEN=$maxlen -v MAX=$massimo '
{
sfmt=sprintf(" %%%ds ", MAXLEN);
printf(sfmt, $2);
for (i=0; i<$1*10/MAX; i++)
printf("=");
printf(" %s KB\n", $1);
}'
rm -f /tmp/$0$$.tmp
4. Scrivere un comando sed che riceve in input l'output del comando uptime e
stampa in output gli ultimi tre valori. L'output di uptime è il seguente
$ uptime
6:34pm up 2 day(s), 49 min(s), 1 user, load average:
0.00, 0.00, 0.02
Output:
load average: 0.05, 0.01, 0.03
Script:
$ uptime | sed 's/.* load/load/'
5. Scrivere un comando sed che prende come input l'output del comando df -k e
stampa solo le linee che cominciano per /.
L'output di df -k è il seguente:
Filesystem
/dev/hda6
/dev/hda5
none
/dev/hda3
/dev/sda4
Output:
/dev/hda6
/dev/hda5
/dev/hda3
/dev/sda4
blocchi di
1K
Usati Disponib. Uso% Montato su
15053684
3601588 10687404 26% /
101089
9381
86489 10% /boot
256956
0
256956
0% /dev/shm
103594
7117
96477
7% /mnt/dati
244464
66560
177904 28% /mnt/zip
15053684
101089
103594
244464
3601588
9381
7117
66560
10687404
86489
96477
177904
26%
10%
7%
28%
/
/boot
/mnt/dati
/mnt/zip
Script:
$ df -k | sed -n '/^\//p'
6. Si inseriscono in un file (il cui nome è dato come parametro), senza
distruggerlo, stringhe lette da input se
a) contengono almeno una lettera minuscola e non contengano numeri
b) contengono almeno un numero e non contengono lettere minuscole
Script:
#!/bin/bash
while echo "vuoi finire(si/no)?"; read fine
test $fine != "si"
do
echo inserisci stringa
read a
echo $a
case $a in
[a-z][a-z]*[^0-9]) echo OK1; echo $a >> $1;;
[0-9][0-9]*[^a-zA-Z]) echo OK2; echo $a >> $1;;
*) echo Stringa non inserita;;
esac
done
7. Si scriva un comando che sposta (su richiesta) tutti i file passati come
argomento in un direttorio specificato come primo parametro.
Esempio di riga di comando:
$movetodir dir file1 file2 ... filen
Script:
#!/bin/bash
case $# in
0|1) echo Usage: movetodir dir file1 file2 ... filen ; exit 1;;
esac
if test -d $1
then
for i in $* # per tutti gli argomenti
do
if test $i != $1
then
echo $i in $1 (y/n)?
read risposta
if test $risposta = "y"
then
if mv $i $1
then echo si $1/$i
else echo Error for $1
fi
fi
fi
done
fi
8. Si scriva uno script che controlla che un dato file sia presente nei
direttori del PATH corrente. Il nome del file è passato come primo e unico
parametro. Quando il nome viene trovato nei sottodirettori viene stampato a
video il percorso in cui il file si trova.
Esempio riga di comando:
$whereis file
Script:
#!/bin/bash
case $# in
0) echo almeno un argomento; exit 1;;
esac
for i in `echo $PATH | tr ':' ' '`
do
if test -e $i/$1 #se esiste
then
if test -e $i/$1
then echo $i/$1 #se è un file
fi
fi
done
Si estenda il file comandi in modo da fornire solo il primo sottodirettorio in
cui si trova un file del nome dato.
9. Si visualizza il contenuto dei file passati come argomento richiedendo per
ciascuno l'assenso all'utente.
Esempio di riga di comando:
$choose file1 file2 file3 ... filen
Script:
#!/bin/bash
for i in $*;
do
echo -n "Visualizzo $i (y/n)? "
read answer
case $answer in
[yY][eE][sS]|[yY]) cat $i;;
esac
done
10. Si scriva uno script che richiamando sed permetta di convertire un file dal
formato DOS (invio codificato con la sequenza 10, 13) al formato UNIX (invio
codificato con 10).
Script:
#!/bin/bash
if [ "$1" != "" ]; then
sed -e 's/\x0d\x0a/\x0a/g'
else
for i in $@; do
cat $i|sed -e 's/\x0d\x0a/\x0a/g'>$i.$$.new
cp -f $i.$$.new $i
rm -rf $i.$$.new
done;
fi
11. Si scriva uno script che confronta il contenuto di due directory (file e
direttori) e riporta in output la lista dei nomi che compaiono in una sola delle
due directory.
Opzionale: Si utilizzi il comando creato nell'esercizio 12 in modo da trovare i
file e i direttori unici in due gerarchie di directory.
Esempio di riga di comando:
$ diversi dir1 dir2
Script:
#!/bin/bash
case $# in
0|1 ) echo Usage: different dir1 dir2; exit 1;;
2) if test ! -d $1 -o ! -d $2
then echo too few parameters; exit 2
fi;;
esac
#cd $1
ls $1 > temp1
ls $2 > temp2
diff temp1 temp2 > temp3
for i in `cat temp3`
do
if test $i != temp1 -a $i != temp2
then
if test -f $1/$i
then echo unico $1/$i
fi
if test -f $2/$i
then echo unico $2/$i
fi
if test -d $1/$i
then echo sottoalbero unico $1/$i;
fi
if test -d $2/$i
then echo sottoalbero unico $2/$i;
fi
fi
done
rm temp1 temp2 temp3
12. Si immagini di avere un file di testo RUBRICA nella propria home che
contiene una rubrica nel seguente formato:
Nominativo:Posta elettronica:Indirizzo:Telefono
Si scriva uno script showperson che cerca un nominativo (passato come unico
parametro)all'interno del file e stampa le informazioni nel seguente formato
Output:
Nome: nominativo
Email: posta elettronica
Address: inidirizzo
Phone: Telefono
Ci si assicuri che solo i messaggi di errore previsti vengano visualizzati sullo
standard output.
Script:
!/bin/bash
if [ $# -lt 1 ] ; then
echo "USAGE: showperson name"
exit 1
fi
MYADDRESSBOOK="$HOME/addressbook"
if [ ! -f "$MYADDRESSBOOK" ] ; then
echo "ERROR: $MYADDESSBOOK does not exist, or is not a file." >&2
exit 1
fi
# get all matches and format them
grep "$1" "$MYADDRESSBOOK" |
awk -F: '{
printf "%-10s %s\n%-10s %s\n%-10s %s\n%-10s %s\n\n",\
"Name:",$1,"Email:",$2,"Address:",$3, "Phone:",$4 ;
}'
exit $?