View Full Version : Esercizi in Linux
superchip
21-04-2004, 15:38
Un saluto a tutti!
Voglio partire col presupposto che di Linux non capisco una "l", quindi, non so dove mettere le mani in nessun posto. Dobbiamo fare due esercitazioni usando gli "shell-script" la prima traccia dice:
"Dato un file giornali contenente per ogni riga due colonne, titolo e copie vendute, a costruire un comando per fornire in output il numero copie di un titolo fornito dall'utente come argomento, oppure un messaggio di non trovato"
La seconda:
" Simulazione di un motore di ricerca: cercare in una directory i file che contengono una parola fornita, insieme al comando, dell'utente. Prima fornisce il numero dei file trovati, poi di ciascuno visualizza il nome e le prime cinque righe del file. controllare anche che l'utente fornisca una parola come argomento del comando.
Arrivato a questo punto, sono riuscito a finire il primo programma; però non funziona. Come posso risolvere questo problema? E per il secondo come devo fare? Quello che ho copiato sotto è il primo script, che nonostante i numerosi tentativi di correzione, non funziona. C'è qualcuno che saprebbe aiutarmi a riguardo?
Grazie 1000
#!bin/bash
declare nome
declare quantita
declare ok
ok=0
nome=$1
ok= grep nome giornali
if [ -z $ok ]
then
echo 'Rivista trovata'
quantita=$(grep $1 giornali | cut -f2)
echo $quantita
else
echo 'Rivista non trovata'
fi
Cominciamo col primo.
Dal man test leggo:
-z STRING
the length of STRING is zero
quindi tu l'hai usato male, avresti dovuto invertire il then con l'else.
Poi non mi sembra che nessuna delle tre variabili dichiarate sia utile.
Non so come si faccia a programmare "per benino", non ho mai studiato su queste cose, cmq io avrei fatto cosi`:
#!/bin/bash
if grep -q "$1" giornali
then
echo 'Rivista trovata'
echo quantita=$(grep $1 giornali | cut -f2)
else
echo 'Rivista non trovata'
fi
Nota queste cose:
l'opzione -q del grep
il percorso corretto di bash
Ah, cmq puoi anche usare le lettere accentate.
Guldo
superchip
21-04-2004, 18:36
Uoa!!! Funzi!!! mitico guldo!!!
Grazie mille!!
Per favore mi puoi dire che tipo di opzione è la grep -q?
Come mai nel codice dell'IF non hai inserito le parentesi quadre? è un nuovo tipo di sintassi? nel manuale che ho scaricato, ci sono le partentesi. E' un errore il mio?
Per il secondo esercizio, ho iniziato in questo modo:
#!/bin/bash
declare nome
declare nfilecartella
declare dir
nome=$1
while [ $1 ge 0 -a $1 le 9 ]
do
nome=$1
done
<<con questa parte di codice, mi sono assicurato che l'utente abbia inserito una parola e non un numero. Un problema in meno>>
Per cercare una parola all'interno del file, come si può fare??
dir=ls
nfilecartella=wc -c dir #sappiamo quanti file ci sono nella dir
e poi?:cry: :cry: :D
lucifero666
21-04-2004, 18:47
#!/bin/bash
result=$(grep $1 giornali)
if [[ ! -z $result ]]
then
echo 'Rivista trovata'
quantita=$(echo $result | cut -d" " -f2)
echo "Quantita' venduta:"
echo $quantita
else
echo 'Rivista non trovata'
exit 1
fi
exit 0
Allora, dovrebbe funzionare adesso;
ho considerato un file "giornali" dove le due colonne sono separate da uno spazio.
Ti dico quali erano i problemi:
1) quando assegni il risultato del grep alla variabile devi inserire quella operazione tra $( ) come facevi giustamente dopo nel caso di quantita
2) come ti avevano fatto notare nel tuo caso la condizione dell'if va' negata, oppure vanno scambiati i due rami. (cioe' se la stringa e' di lunghezza zero segnali che non hai trovato nulla, e viceversa)
3)Quando fai la cut devi stabilire anche il delimitatore nella stringa per poter selezionare un campo.
Lo puoi fare con l'opzione -d(delimitatore)
Nel tuo caso dato che le due colonne del file sono separate da uno spazio ho usato quello come delimitatore.
Ho tolto i declare perche' in questo caso non servivano...
il comando declare e' utile quando vuoi specificare particolari proprieta' della variabile.
Spero di esserti stato di aiuto.
Keep on scripting! ;)
Io farei cosi`:
#!/bin/bash
if [ $# = 0 ]; then echo "Voglio un argomento!"; exit 0; fi
j=0
for i in $(ls)
do
grep -q "$1" "$i" && j=$[$j+1]
done
echo "Ho trovato $j file(s)."
for i in $(ls .)
do
grep -q "$1" "$i" &&
echo File: "$i" &&
head -n 5 "$i"
done
exit 0
Pero` adesso basta.
Leggiti bene le pagine man di grep e test; poi magari guarda altrettanto bene i capitoli sulla bash degli "appunti" di daniele giacomini.
Buon scripting! :D
Guldo
Ah, dimenticavo, non saprei come controllare che l'utente inserisca una parola quando invoca lo script; il mio script si limita a controllare che l'utente inserisca almeno 1 argomento, il che significa che puo` inserirne anche piu` d'uno (ma saranno tutti ignorati tranne il primo), e che puo` inserire parole o numeri.
Del resto il tuo esempio (cmq sbagliato nella sintassi) si limitava a controllare che venisse inserito qualcosa compreso tra 0 e 9...
Guldo
superchip
21-04-2004, 20:53
Ok basta... non voglio essere invasivo! :p voglio imparare qualcosina!!!:p
Per esempio: cosa non andava nel mio primo script? in fondo è molto simile ai vostri... in uno dei miei Tentativi, ho provato modificare il comando ok sempre con le stesse istruzioni, e subito dopo ho fatto una echo di ok per vedere se al suo interno ci fosse qualcosa. Come mai la echo dava come risultato uno spazio? E poi non riesca a capire una cosa: perché Lucifero666 hai utilizzato le parentesi quadre mentre guldo no? che ruolo giocano le parentesi squadre nel test di Linux? poi giusto un'ultima curiosità: a cosa serve la exit che è presente nei due script?
Grazie ancora raga! siete due mostri!!!
Un link per rispondere alle tue domande:
http://tldp.org/LDP/abs/html/index.html
lucifero666
22-04-2004, 10:10
Allora, per quanto riguarda le parentesi quadre effettivamente in questo caso potevano non essere utilizzate; in generale esse sono un sinonimo per il comando "test" di linux, che non fa' altro che eseguire (testare) l'espressione che gli viene "assegnata".
In questo caso essendoci il costrutto if then else si poteva evitare di mettere la test.
oppure volendo non utilizzare il costrutto if then else avresti potuto scrivere una cosa del genere:
#!/bin/bash
result=$(grep $1 giornali)
[[ ! -z $result ]] && echo 'Rivista trovata' && echo "Quantita' venduta: $(echo $result | cut -d" " -f2) " && exit 0
echo "Rivista non trovata"
exit 1
Come vedi il codice e' piu' corto ma anche molto piu' criptico, in questo caso l'idea e' che viene eseguito il primo test, se questo va' bene (ovvero ritorna true) sara' eseguito il secondo comando, e cosi via a catena fino al comando di exit 0;
se il test tornera' false di conseguenza non verranno eseguiti tutti gli altri comandi, e si passera' direttamente al comando successivo di "rivista non trovata".
Come sinonimo della test posso utilizzare sia la singola "[" oppure come in questo caso
la doppia "[[" , questa scelta e' dovuta al fatto che alcuni operatori come "&&" o "||" vengono interpretati correttamente nel secondo caso, ma per tutto questo ti rimando al man della shell.
Per quanto riguarda gli exit l'utilizzo di questi dipende dal fatto che in unix, per convenzione, ogni comando (o script..) termina "ritornando" un exit status.
Ovvero, quando io eseguo un qualunque comando se questo termina correttamente mi tornera' come exit status 0, altrimenti un numero diverso da zero, che in generale corrisponde ad un particolare errore.
Questo ovviamente e' molto utile per controllare l'assenza di errori, quindi e' fortemente consigliato seguire questa convenzione.
Byez.!
;)
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.