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 $?