View Full Version : [Bash] Malfunzionamento sort e iniziale stringa
Questo è il codice del compito che io ho scritto.
#!/bin/bash
# COMPITO D'ESAME 12-09-09
#
# Lorenzo Carnevale
# Lorenzo-Carnevale-373780-Esercizio1.sh - Mer 20 Gen 2010 12:03:34 CET
#
# Testo:
# Creare uno script che trovi tutti gli utenti registrati nel sistema
# che abbiano come shell i comandi "false" e "nologin" (utenti che non
# hanno associata una shell interattiva). Comunicare a video la lista
# ottenuta, contenente i campi: <usarname> <uid>. La lista deve essere
# mostrata in ordine numerico crescente rispetto al campo <uid>.
# (Suggerimento: per l'ordinamento usare il comando sort):
#
clear
temp_IFS=$IFS
IFS=$'\n'
for i in $(cat /etc/passwd | grep -v "#" | (grep "false" || grep "nologin"))
do
IFS=$temp_IFS
USERTEMP=$(echo $i | awk -F: '{printf "%s\n", $1}')
UIDTEMP=$(echo $i | awk -F: '{printf "%s\n", $3}')
SHELLTEMP=$(echo $i | awk -F: '{printf "%s\n", $7}')
# Seleziono solo gli specifici campi richiesti
echo "$UIDTEMP:$USERTEMP:$SHELLTEMP" | sort -nr
done
Il problema sta nel sort, non riesco ad effettuare l'ordinamento numerico al contrario (il comando sort è flaggato in controcorrente al compito appositamente per avere l'effetto che dico io perché l'output mi usciva già ordinato nel modo corretto).
Inoltre si richiede il seguente secondo punto:
Facendo riferimento all'esercizio 1, specificare le istruzioni necessarie, da inserire al prompt della shell, per contare gli utenti forniti in uscita dallo script che iniziano con la lettera "r". L'intera operazione deve essere eseguita in una singola linea di comando (utilizzare la pipe).
Questo è il mio svolgimento:
./Lorenzo-Carnevale-373780-Esercizio1.sh | awk -F: '{printf "%s\n", $2}' | grep "r " | wc -l
L'output esce correttamente ma non sono pienamente sicuro della validità del codice.
sorry al momento nn ho sottomano file passwd da controllare :)
però:
1-il compito vuole questo <usarname> <uid>
e tu gli metti "$UIDTEMP:$USERTEMP:$SHELLTEMP"
nn mi pare corretto :)
2- come mai estrai la shell? nn mi pare venga richiesta
3- non capisco che problemi hai con il sort...una volta che hai la lista <usarname> <uid> puoi sortare tranquillamente col
sort -k 2 -n (k=campo n=numerico), ma nn mi è chiara la questione del -r
4- una volta che hai sempre la lista in formato come sopra, non serve nessun awk, in pipe allo script metti:
grep "^r" |wc -l
così sorti tutti quelli che cominciano con r (magari -i per il case sensitive) e li conti...
sono solo info al volo poi magari vediamo meglio :)
PS: tanto per rendere + snello il codice, soprattutto con file molto grossi....
userei l'awk per trattare direttamente il file stesso, senza tanti IF che appesantiscono di brutto :)
se puoi postare o mandare via mail il file magari ci do un okkio + specifico :)
nn puoi fargli TUTTO in una riga? :)
o al massimo 2 :)
cat /etc/passwd | grep -v "#" | (grep "false$" || grep "nologin$") | awk -F: '{print $1" "$3}' |sort -k 2 n
cat /etc/passwd | grep -v "#" | (grep "false$" || grep "nologin$") | awk -F: '{print $1" "$3}' |grep -i "^r" |wc -l
1-il compito vuole questo <usarname> <uid>
e tu gli metti "$UIDTEMP:$USERTEMP:$SHELLTEMP"
2- come mai estrai la shell? nn mi pare venga richiesta
Ho inserito questi perché volevo verificare il corretto svolgimento del programma. Diciamo che è una dicitura da sviluppatore e non da utente finale :D
Poi certo, non è stato richiesto dal compito.
3- non capisco che problemi hai con il sort...una volta che hai la lista <usarname> <uid> puoi sortare tranquillamente col
sort -k 2 -n (k=campo n=numerico), ma nn mi è chiara la questione del -r
La scelta del campo non sapevo fosse possibile. Usa le variabili IFS per sapere da dove inizia il secondo campo?
La storia del "-r" deriva dalla voglia di effettuare un ordinamento decrescente (e non crescente, come il testo chiedeva) perché io mi ritrovavo, anche senza sort, i campi ordinati come richiesto.
4- una volta che hai sempre la lista in formato come sopra, non serve nessun awk, in pipe allo script metti:
grep "^r" |wc -l
così sorti tutti quelli che cominciano con r (magari -i per il case sensitive) e li conti...
Questo avviene se il primo campo che io mando in output finale è l'USER oppure in ogni caso?
nn puoi fargli TUTTO in una riga?
o al massimo 2
Magari era pure possibile, però non so se il prof era d'accordo :D
Comunque grazie per la disponibilità, appena sono a casa provo i cambiamenti e ti faccio sapere!
Ho inserito questi perché volevo verificare il corretto svolgimento del programma. Diciamo che è una dicitura da sviluppatore e non da utente finale :D
Poi certo, non è stato richiesto dal compito.
ok allora vai cmq di awk con lo spazio :)
La scelta del campo non sapevo fosse possibile. Usa le variabili IFS per sapere da dove inizia il secondo campo?
La storia del "-r" deriva dalla voglia di effettuare un ordinamento decrescente (e non crescente, come il testo chiedeva) perché io mi ritrovavo, anche senza sort, i campi ordinati come richiesto.
esatto IFS e scelta del campo :)
ok per controllo puoi usare il -r ero io che nn capivo a che ti serviva :)
Questo avviene se il primo campo che io mando in output finale è l'USER oppure in ogni caso?
no chiaramente avviene solo se il primo campo è USER il ^ sta a significare proprio l'inizio :)
de nada fammi sapere come va ;)
Modificando il mio sorgente non effettua lo stesso il sort, come se non capisse qual'è il campo che deve ordinare. Proprio se ne frega.
#!/bin/bash
clear
temp_IFS=$IFS
IFS=$'\n'
for i in $(cat /etc/passwd | grep -v "#" | (grep "false" || grep "nologin"))
do
IFS=$temp_IFS
USERTEMP=$(echo $i | awk -F: '{printf "%s\n", $1}')
UIDTEMP=$(echo $i | awk -F: '{printf "%s\n", $3}')
# Seleziono solo gli specifici campi richiesti
echo "$USERTEMP $UIDTEMP" | sort -k 2 -nr
done
La parte sottolineata è quella che sembra dare problemi.
Poi ho provato l'altro codice, quello mono-riga (con il "-" davanti alla "n" che avevi dimenticato :D ), e funziona perfettamente nell'ordinamento sia del secondo che eventualmente anche del primo. Anche per questo non capisco perché non debba funzionare il codice di partenza, la formattazione dell'output è sempre uguale (con lo spazio tra le due parole).
Ho notato una cosa che tu hai aggiunto rispetto al mio codice, parlo delle "$"
... (grep "false$" || grep "nologin$") ...
A che servono?
Modificando il mio sorgente non effettua lo stesso il sort, come se non capisse qual'è il campo che deve ordinare. Proprio se ne frega.
#!/bin/bash
clear
temp_IFS=$IFS
IFS=$'\n'
for i in $(cat /etc/passwd | grep -v "#" | (grep "false" || grep "nologin"))
do
IFS=$temp_IFS
USERTEMP=$(echo $i | awk -F: '{printf "%s\n", $1}')
UIDTEMP=$(echo $i | awk -F: '{printf "%s\n", $3}')
# Seleziono solo gli specifici campi richiesti
echo "$USERTEMP $UIDTEMP" | sort -k 2 -nr
done
La parte sottolineata è quella che sembra dare problemi.
Poi ho provato l'altro codice, quello mono-riga (con il "-" davanti alla "n" che avevi dimenticato :D ), e funziona perfettamente nell'ordinamento sia del secondo che eventualmente anche del primo. Anche per questo non capisco perché non debba funzionare il codice di partenza, la formattazione dell'output è sempre uguale (con lo spazio tra le due parole).
Ho notato una cosa che tu hai aggiunto rispetto al mio codice, parlo delle "$"
... (grep "false$" || grep "nologin$") ...
A che servono?
nel tuo IF, ad ogni ciclo, tu fai l'echo.....
il che vuol dire che fai 1 echo ogni volta....
quindi cerchi di fare il sort ad ogni ciclo...
quindi sorti una riga sola ;)
^=inizio riga
$=fine riga ;)
PS: cmq per lo script preferirei senza ombra di dubbio l'awk... secondo me anche il prof lo farebbe ;)
nel tuo IF, ad ogni ciclo, tu fai l'echo.....
il che vuol dire che fai 1 echo ogni volta....
quindi cerchi di fare il sort ad ogni ciclo...
quindi sorti una riga sola ;)
E' vero, questi sono i palesi errori di gioventù. Si vede che tu sei già più afferrato :D
Ma allora che mi conviene fare? Un'idea è reindirizzare in un file temporaneo che echerò successivamente per sortare il contenuto. Ma mi sembra troppo ruvido come procedimento.
^=inizio riga
$=fine riga
Ok, mi devo ripassare qualche cosa :mc:
PS: cmq per lo script preferirei senza ombra di dubbio l'awk... secondo me anche il prof lo farebbe
La cosa bella è che lui neanche l'ha fatto a lezione (nonostante nel programma è inserito) e quindi le sue soluzioni sono presentate con annidamenti di for ed if che non ti conto. A me, onestamnte, con l'awk viene tutto più facile.
ehehehe beh siamo partiti tutti dalla gioventù...ma io nn sono mica molto lontano :)
cmq prova una cosa del genere
for i in $(cat /etc/passwd | grep -v "#" | (grep "false" || grep "nologin"))
do
IFS=$temp_IFS
USERTEMP=$(echo $i | awk -F: '{printf "%s\n", $1}')
UIDTEMP=$(echo $i | awk -F: '{printf "%s\n", $3}')
SHELLTEMP=$(echo $i | awk -F: '{printf "%s\n", $7}')
# Seleziono solo gli specifici campi richiesti
LINE="$UIDTEMP $USERTEMP"
LINES="$LINES$LINE\n"
done
echo "LINES" | sort -k 2 -n
ehehehe beh siamo partiti tutti dalla gioventù...ma io nn sono mica molto lontano :)
cmq prova una cosa del genere
for i in $(cat /etc/passwd | grep -v "#" | (grep "false" || grep "nologin"))
do
IFS=$temp_IFS
USERTEMP=$(echo $i | awk -F: '{printf "%s\n", $1}')
UIDTEMP=$(echo $i | awk -F: '{printf "%s\n", $3}')
SHELLTEMP=$(echo $i | awk -F: '{printf "%s\n", $7}')
# Seleziono solo gli specifici campi richiesti
LINE="$UIDTEMP $USERTEMP"
LINES="$LINES$LINE\n"
done
echo "LINES" | sort -k 2 -n
Non va neanche questo, mentre così funziona:
clear
temp_IFS=$IFS
IFS=$'\n'
for i in $(cat /etc/passwd | grep -v "#" | (grep "false" || grep "nologin"))
do
IFS=$temp_IFS
USERTEMP=$(echo $i | awk -F: '{printf "%s\n", $1}')
UIDTEMP=$(echo $i | awk -F: '{printf "%s\n", $3}')
# Seleziono solo gli specifici campi richiesti
echo "$USERTEMP $UIDTEMP" >> filetemp.txt
done
cat filetemp.txt | sort -k 2 -n
rm filetemp.txt
scusa, colpa mia...
ho scritto un po di fretta
echo "LINES" | sort -k 2 -n
è chiaramente sbagliato :)
echo "$LINES" | sort -k 2 -n
questo già dovrebbe andare meglio :)
scusa, colpa mia...
ho scritto un po di fretta
echo "LINES" | sort -k 2 -n
è chiaramente sbagliato :)
echo "$LINES" | sort -k 2 -n
questo già dovrebbe andare meglio :)
No, no...di quello mi ero accorto anche perché mi usciva in output "LINES".
Invece mi dice non uso correttamente sort e di consultare l'aiuto con sort --help
No, no...di quello mi ero accorto anche perché mi usciva in output "LINES".
Invece mi dice non uso correttamente sort e di consultare l'aiuto con sort --help
nn capisco come mai...
se fai l'echo "$LINES" senza il sort che ti compare a video??
ti comparirà tutto su una riga....
nn capisco come mai...
se fai l'echo "$LINES" senza il sort che ti compare a video??
ti comparirà tutto su una riga....
Ah si, si...non so che avevo combinato.
Li vedo uno di seguito all'altro, però siamo sempre li....non li ordina!
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.