Shell: Parte 3 (Soluzioni)¶
Soluzioni¶
- Soluzioni:
echo *
contiene una wildcard; la shell effettua la wildcard expansion sostituendo*
con la lista dei path che fanno il match con la wildcard. In questo caso*
fa il match con i file e le directory contenuti nella directory corrente. Quindiecho
stampa a schermo i path che hanno fatto match.echo '*'
: qui la wildcard e’ protetta dalle virgolette, niente wildcard expansion.echo
stampa il carattere*
a schermo.cat data/simple1/*.txt
?
cat data/simple1/*.txt
.cat data/simple1/*.abc
.cat data/simple1/*.txt > temp
.cat data/simple1/*.abc >> temp
. Usiamo>>
per non sovrascriveretemp
.- Soluzioni:
ls /usr/bin/[0-9]*
ls /usr/bin/x*x
ls /usr/bin/x* /usr/bin/x*
Soluzioni¶
- Soluzioni:
echo *
contiene una wildcard; la shell effettua la wildcard expansion sostituendo*
con la lista dei path che fanno il match con la wildcard. In questo caso*
fa il match con i file e le directory contenuti nella directory corrente. Quindiecho
stampa a schermo i path che hanno fatto match.echo '*'
: qui la wildcard e’ protetta dalle virgolette, niente wildcard expansion.echo
stampa il carattere*
a schermo.cat data/simple1/*.txt
?
cat data/simple1/*.txt
.cat data/simple1/*.abc
.cat data/simple1/*.txt > temp
.cat data/simple1/*.abc >> temp
. Usiamo>>
per non sovrascriveretemp
.- Soluzioni:
ls /usr/bin/[0-9]*
ls /usr/bin/x*x
ls /usr/bin/x* /usr/bin/x*
Soluzione:
wc A
stampa il numero di righe, parole e caratteri nel fileA
.wc
incat A | wc
stampa il numero di righe, parole e caratteri nellostdin
, ch in questo caso combacia con il contenuto diA
.
Quindi in principio fanno la stessa cosa. Attenzione pero’ che l’output nei due casi e’ leggermente diverso.
Soluzione:
wc -l A
stampa il numero di righe nel fileA
.cat A | tr '\n' ' ' | wc -w
passa i contenuti diA
alla pipe, che li passa atr
, che sostituisce tutti i caratteri di a capo\n
con spazi (cioe’ mette tutto il testo diA
in una riga sola, senza\n
alla fine); poiwc
conta le parole nel risultato.
Quindi i due comandi fanno cose completamente diverse: il primo conta le righe, il secondo le parole.
ls /usr/bin | wc -l
ls -S /usr/bin
, oppure:ls -l /usr/bin | tr -s ' ' | cut -d' ' -f5,9 | sort -n -k1
ls -S /usr/bin | tail -n 1
, oppure:ls -l /usr/bin | tr -s ' ' | cut -d' ' -f5,9 | sort -n -k1 | head -n 1
Soluzione:
cat data/numbers.[12] | sort -n
Soluzione:
cat data/numbers.[12] | sort -n -r oppure:: cat data/numbers.[12] | sort -n | tac
Controllo:
ls /usr/bin | sort | uniq -d Non stampa nessun duplicato: la risposta e' no. (Basta pensare che una directory non puo' contenere due file con lo stesso nome.)
Soluzione:
ls data/deep1/*/* > lista1.txt ls data/deep2/*/*/* > lista2.txt ls data/deep3/*/*/*/* > lista3.txt
Soluzione:
cat data/deep1/*/* > lista1.txt cat data/deep2/*/*/* > lista2.txt cat data/deep3/*/*/*/* > lista3.txt
Soluzione:
cat data/deep1/*/* | grep '[13579]$' | wc -l Risposta: 50.
- Soluzioni:
echo ACAB | cut -dC -f2
stampa la scrittaACAB
, la passa acut
, che usandoC
come delimitatore stampa la seconda colonna:AB
.
echo BACA | cut -dA -f1,2
stampa la scrittaBACA
, la passa acut
, che usandoA
come delimitatore stampa la prima e seconda colonna:BAC
.
- Soluzioni:
wc -m A
stampa il numero di caratteri nel fileA
.cat A | wc | tr -s ' ' | cut -d' ' -f4
stampa i contenuti diA
a schermo; poiwc
stampa il numero di righe, parole e caratteri a schermo su una sola riga di output; poitr
riduce spazi multipli ad uno solo; infine cut, usando lo spazio `` `` come delimitatore, stampa la quarta colonna – che corrisponde al numero di caratteri nel file. Quindi il risultato e’ come sopra.
Nell’output di
ls -l
il proprietario si trova nella terza colonna. Quindi e’ sufficiente fare:ls -l /usr/bin | tr -s ' ' | sort -k 3
Ci sono almeno due possibilita’:
ls -l /usr/bin | tr -s ' ' | sort -k 3 | tac
oppure:
ls -l /usr/bin | tr -s ' ' | sort -k 3 -r
Per stampare la lista dei file ed ordinarli dal
ls /usr/bin/ -l | tr -s ' ' | sort -n -k 5
L’output sara’ simile a questo:
$ ls /usr/bin/ -l | tr -s ' ' | sort -n -k 5 total 260336 lrwxrwxrwx 1 root root 1 May 6 2013 X11 -> . lrwxrwxrwx 1 root root 2 Aug 1 19:50 ghostscript -> gs lrwxrwxrwx 1 root root 2 Aug 23 12:49 inimf -> mf lrwxrwxrwx 1 root root 2 Dec 13 2014 mcdiff -> mc lrwxrwxrwx 1 root root 2 Dec 13 2014 mcedit -> mc lrwxrwxrwx 1 root root 2 Dec 13 2014 mcview -> mc lrwxrwxrwx 1 root root 2 Jul 3 21:44 unxz -> xz lrwxrwxrwx 1 root root 2 Jul 3 21:44 xzcat -> xz ...
I file sono ordinati correttamente; ora dobbiamo estrarre la seconda riga (la prima e’ un sommario stampato da
ls
, e dobbiamo scartarla). Per estrarre la seconda riga posso aggiungerehead
etail
:... | head -n 2 | tail -n 1
oppure usare
grep
:... | grep -v '^total' | head -n 1
In entrambi i casi ottengo una riga sola, simile a questa:
lrwxrwxrwx 1 root root 1 May 6 2013 X11 -> .
A questo punto e’ sufficiente estrarre la dimension (nel mio caso
1
) aggiungendocut
:... | cut -d' ' -f5
Ci sono un numero di alternative altrettanto valide.
Simile a prima:
ls /usr/bin -l | tr -s ' ' | sort -n -k 5 | tail -n 1 | cut -d' ' -f9
Stampo la lista dei file, estraggo le dimensioni, e uso
sort | uniq
:ls /usr/bin -l | tr -s ' ' | sort -n -k 5 | cut -d' ' -f5 | sort | uniq -d | wc -l Il ``wc -l`` alla fine serve per contare il numero di duplicati trovati da ``uniq -d``. Nel mio caso ce ne sono 166. In breve, la risposta e' si'.
- Soluzioni:
.
: valida, un carattere qualunque, in qualunque posizione. Leggi: una stringa di almeno un carattere..*
: valida, un numero arbitrario di caratteri qualunque, anche zero. Leggi: una stringa qualunque.[09]{2}
: valida, esattamente due caratteri0
oppure9
. Leggi: fa match con00
,09
,90
e99
.[0-9]{2}
: valida, esattamente due caratteri numerici qualunque. Leggi: stringhe di due caratteri tra0
e9
.*
: valida, il carattere asterisco*
. (Si noti la differenza con le wildcards!)[
: non valida.[[]
: valida, fa match con la parentesi quadra aperta[
in qualunque posizione.^.3
: valida, fa match con stringhe che iniziano con un carattere qualunque e proseguono con3
.^.{3}
: valida, fa il match con stringhe lunghe almeno tre caratteri..{3}$
: valida, come sopra.^>
: valida, fa match con stringhe che iniziano per>
.AA
: valida, fa match con stringhe che contengono la sotto-stringaAA
, in qualunque posizione.^AA$
: valida, fa match on la sola stringaAA
.aA
: valida, fa match con stringhe che contengono la sotto-stringaaA
, in qualunque posizione.[aA]
: valida, fa match con stringhe che contengono unaa
o unaA
, o entrambe, in qualunque posizione.word
: valida, fa match con stringhe che contengono la parolaword
, in qualunque posizione.w..d
: valida, fa match con stringhe che contengono parole che cominciano conw
, finiscono perd
, e sono lunghe quattro caratteri.^$
: valida, fa match con righe vuote.[}{]
: valida, fa match con righe che contengono una alemno parentesi graffa.[0-9]+
: valida, fa match con righe che contengono una sotto-stringa numerica lunga almeno un carattere.
- Soluzioni:
Tutti i caratteri alfanumerici, maiuscoli e minuscoli:
[a-zA-Z]
Le righe contenenti solo spazi:
^[ ]*$
Le righe che contengono punti esclamativi o punti interrogativi:
[!?]
I giorni della settimana (nel modo piu’ compatto possibile) Senza lettere accentate:
(lune|marte|mercole|giove|vener)di|sabato (Non uso lettere accentate per comodita'.)
Le parole di radice
frazion
-, ad esempio: frazione, frazionario, etc.:frazion.*
I multipli di 10, i multipli di 5, i numeri dispari:
[0-9]*0 [0-9]*[05] [0-9]*[13579]
I numeri razionali come frazione:
[0-9]*/[0-9]*
I numeri razionali in notazione decimale, ad esempio: 1.34, .99, 17., 3:
[0-9]*(\.[0-9]*)?
I numeri razionali in notazione scientifica, ad esempio: 1.34e10, 1.34e-10:
[0-9]*(\.[0-9]*|[0-9]+e[+-]?[0-9]+)?
Le somme (esempio: a+b+c+d, a+b, etc.) di lunghezza arbitraria, dove a, b, c, ... sono numeri interi:
[0-9]+(\+[0-9]+)+
- Le somme di due moltiplicazioni, cose come: (2 * 3 * 2) + (5 * 7), (6 * 2) + (4 * 3), etc.
E’ sufficiente generalizzare la soluzione all’esercizio precedente.
Quanti multipli di 5 ci sono in
data/deep3
?:cat data/deep3/*/*/*/sign | cut -d' ' -f7-9 | tr -d ',' | tr ' ' '\n' | grep '[05]$'
Quanti di due cifre?:
cat data/deep3/*/*/*/sign | cut -d' ' -f7-9 | tr -d ',' | tr ' ' '\n' | grep '^[05]$'
oppure, piu’ lungo:
cat data/deep3/*/*/*/sign | cut -d' ' -f7-9 | tr -d ',' | tr ' ' '\n' | grep '[05]$' | grep '^..$'