Exercicis de les diapositives Shell Scripting
Escriu una funció que calculi el màxim d'una llista de nombres enters.
#!/bin/bash
function maximum {
# TODO
}
maximum 4 8 15 16 23 42
echo "Maximum [4 8 15 16 23 42] is: $?"
exit 0
# Sortida: Maximum [4 8 15 16 23 42] is: 42
Solució (versió 0)
En aquesta versió s'usa l'operador [ ]
per a comparar els nombres. Això requereix inicialitzar la variable max
a 0. També cal $
davant de les variables i
i max
. Això és perquè l'operador [ ]
és un operador de substitució de variables i necessita expandir les variables abans de comparar-les. Expandir una variable significa substituir-la pel seu valor.
#!/bin/bash
function maximum {
max=0
for i in $@; do
if [ "$i" -gt "$max" ]; then
max=$i
fi
done
return $max
}
Solució (versió 1)
En aquesta versió s'usa l'operador aritmètic (( ))
per a comparar els nombres. Això permet evitar la inicialització de la variable max
a 0. Tampoc cal $
davant de les variables i
i max
. Això és perquè l'operador (( ))
no és un operador de substitució de variables, sinó un operador aritmètic.
#!/bin/bash
function maximum {
for i in $@; do
if (( i > max )); then
max=$i
fi
done
return $max
}
Un altra versió més compacta és la següent:
#!/bin/bash
function maximum {
for i in $@; do
(( i > max )) && max=$i
done
return $max
}
Solució (versió 2)
Un altra possible solució és utilitzant el bucle while
i l'operador expr
. També utilitza l'operador shift
per a processar els paràmetres.
#!/bin/bash
function maximum {
max=0
while [ $# -gt 0 ]; do
if [ `expr $1 \> $max` -eq 1 ]; then
max=$1
fi
shift
done
return $max
}
Solució (versió 3)
Un altra possible solució és utilitzant el bucle for
i recorrent utilitzant l'índex i
. En aquest cas, utilitzem la sintaxi ${!i}
per a accedir al valor de la variable i
. L'operador '!és un operador de substitució de variables i necessita expandir la variable
i` abans de substituir-la pel seu valor.
#!/bin/bash
function maximum {
max=0
for (( i=1; i<=$#; i++ )); do
if (( ${!i} > max )); then
max=${!i}
fi
done
return $max
}
o bé utilitzant el shift:
#!/bin/bash
function maximum {
mida=$#
max=0
for (( i=1; i<=$mida; i++ )); do
if (( $1 > max )); then
max=$1
fi
shift
done
return $max
}
o bé accedint directament als vectors de paràmetres $@ indexat per $i:
#!/bin/bash
function maximum {
declare -a array=("$@")
max=${array[0]}
for ((i=1; i<${#array[@]}; i++)); do
if (( ${array[i]} > $max )); then
max=${array[i]}
fi
done
echo $max
}
Exercici 2
#!/bin/bash
mkdir -p test
touch test/fitxer1.txt
touch test/fitxer2.txt
touch test/fitxer3.c
touch test/fitxer4.txt
# TODO
echo "Fitxers amb extensió .txt modificats a .old:"
ls test/*.old
# un altra forma per expandir el contingut de ls
ls test/*.{old}
rm -rf test
exit 0
# Sortida:
# Fitxers amb extensió .txt modificats a .old:
# fitxer1.old fitxer2.old fitxer4.old
Solució
#!/bin/bash
mkdir -p test
touch test/fitxer1.txt
touch test/fitxer2.txt
touch test/fitxer3.c
touch test/fitxer4.txt
for i in test/*.txt; do
mv $i ${i%.txt}.old
done
echo "Fitxers amb extensió .txt modificats a .old:"
ls test/*.old
rm -rf test
La comanda ls test/*.old
mostra els fitxers amb extensió .old
que hi ha al directori test
.
Per exemple:
mkdir -p test
touch test/fitxer1.txt
touch test/fitxer2.txt
touch test/fitxer3.c
touch test/fitxer4.txt
bash -c 'ls test/*.c'
sh -c 'ls test/*.c'
rm -rf test
Un altra forma de mostrar els fitxers amb extensió .old és utilitzant la comanda grep
:
mkdir -p test
touch test/fitxer1.txt
touch test/fitxer2.txt
touch test/fitxer3.c
touch test/fitxer4.txt
bash -c 'ls test | grep '\.c$''
sh -c 'ls test | grep '\.c$''
# A classe us he posat *.c però per funcionar amb * necessiteu posar -e *.c
bash -c 'ls test | grep -E '*.c$''
# grep: warning: * at start of expression
Per tant, es millor utilitzar el grep inicial.
# A classe heu comentat un altra solució
bash -c 'ls test/${1:-*}.c'
# En aquest cas ${1:-*} és una substitució de paràmetres. Si no hi ha paràmetres, el valor per defecte és *.
# Es pot simplificar així:
bash -c 'ls test/${1-*}.c'
# Finalment, es pot utilitzar la comanda find:
bash -c 'find test -name "*.c"'
sh -c 'find test -name "*.c"'
rm -rf test
Exercici 3
Crea un script que llegeixi un fitxer de text amb el nom users.txt i que contingui una llista de noms d'usuari. El format del fitxer és el següent: user;password;status. Aquest script ha de mostrar per pantalla tots els atributs dels usuaris que estan actius (status=1).
Solució
#!/bin/bash
cat << EOF > users.txt
user1;password1;1
user2;password2;0
user3;password3;1
user4;password4;0
EOF
IFS=';'
while read user password status; do
echo "User: $user"
echo "Password: $password"
echo "Status: $status"
done < users.txt
rm users.txt