a l’inici de l’script…
set -o errexit # Si una comanda falla, l'script s'atura, enlloc de continuar amb la següent línia set -o nounset # Farà que l'script falli quan s'intenti acccedir a una variable no definida set -o pipefail # Farà que una comanda falli si l'error és dins un pipe if [[ "${TRACE-0}" == "1" ]]; then set -o xtrace; fi # Activa el mode debug si executem l'script amb "TRACE=1 ./script.sh" enllo de "./script.sh"
si mostrem missatges d’error, millor redirigir-los a stderr …
echo 'Something unexpected happened' >&2
echo de text i variables
# ULL!!! Sempre és millor posar les variables entre cometes dobles " echo "hola $nom"
variable de només lectura
readonly PI=3.14159
guardar resultat d’una comanda a una variable
avui=$(date) # (actual) avui=`date` # (antic)
opcions
#!/bin/bash while getopts 'lha:' OPTION; do case "$OPTION" in l) echo "has passat l'opció '-l'" ;; h) echo "has passat l'opció '-h'" ;; a) avalue="$OPTARG" echo "has passat l'opció '-a' amb el valor '$OPTARG'" ;; ?) echo "com utilitzar l'script: $(basename \$0) [-l] [-h] [-a algun_valor]" >&2 exit 1 ;; esac done shift "$(($OPTIND -1))"
En el cas anterior, si passem més d’un valor a l’opció “-a”, només es tractarà el primer valor. Per exemple, si el valor és hola món, només s’agafarà hola. A món hi podrem accedir amb $1, que ho veurem a continuació.
arguments i variables especials
$0 nom de l'script $1 argument 1 $2 argument 2 ... $$ L'id del proceso del shell actual. $# El número total d'arguments passats a l'script. $@ El valor de tots els arguments passats a l'script. $? L'estat de sortida de l'última comanda executada. $! L'ID del procés de l'última comanda executada.
arrays
arxius=("a1.txt" "a2.txt" "a3.txt" "a4.txt" "a5.txt") echo {arxius[0]} # mostra a1.txt echo ${arxius[*]} # mostra a1.txt a2.txt a3.txt a4.txt a5.txt echo ${#archivos[@]} # mostra 5, la quantitat de valors que té l'array arxius+=("a6.txt") # afegir valor a l'array unset arxius[2] # esborrar a3.txt de l'array unset arxius # buida tot l'array
càlculs aritmètics
total=$((2 + 3)) # 5 + suma - resta / divisió * multiplicació ** potencia % mòdul echo "scale=2; 30 * (9/5) + 32" | bc -l # mostrarà 84.20 - bc per treballar amb decimals, scale per només mostrar-ne dos
cadenes
distro="Ubuntu" echo ${#distro} # mostrarà 6, la llargada de la cadena echo ${distro:0:2} # mostrarà "Ub", els dos caràcters després de la posició 0 echo ${distro:2} # mostarà "untu", mostrarà a partir del 2n caràcter cadena="Text prova prova gran" echo ${cadena/prova/kaka} # canviarà "prova" per "kaka" (només una vegada) echo ${cadena//prova/kaka} # canviarà "prova" per "kaka" (totes les coincidències) echo ${cadena/gran} # esborrarà "gran" echo ${cadena/prova} # esborrarà prova (només una vegada) echo ${cadena//prova} # esborrarà prova (totes les coincidències) ${cadena^^} # converteix a majúscules ${cadena,,} # converteix a minúscules ${cadena^} # converteix 1a lletra de la cadena a majúscules ${cadena^} # converteix 1a lletra de la cadena a minúscules ${cadena^^[po]} # converteix les lletres "p" i "o" a majúscules
condicionals
# # ULL!!! millor utilitzar [[ ]] enlloc de [ ] # # if / else if [ $(whoami) = "root" ] then echo "ets root" elif [ $(whoami) = "manel" ] then echo "ets en manel" else echo "ets $(whoami)" fi # diferents opcions dels condicionals (els podem veure tots amb "man test")... -n VAR - True if the length of VAR is greater than zero. -z VAR - True if the VAR is empty. STRING1 = STRING2 - True if STRING1 and STRING2 are equal. STRING1 != STRING2 - True if STRING1 and STRING2 are not equal. INTEGER1 -eq INTEGER2 - True if INTEGER1 and INTEGER2 are equal. INTEGER1 -gt INTEGER2 - True if INTEGER1 is greater than INTEGER2. INTEGER1 -lt INTEGER2 - True if INTEGER1 is less than INTEGER2. INTEGER1 -ge INTEGER2 - True if INTEGER1 is equal or greater than INTEGER2. INTEGER1 -le INTEGER2 - True if INTEGER1 is equal or less than INTEGER2. -h FILE - True if the FILE exists and is a symbolic link. -r FILE - True if the FILE exists and is readable. -w FILE - True if the FILE exists and is writable. -x FILE - True if the FILE exists and is executable. -d FILE - True if the FILE exists and is a directory. -e FILE - True if the FILE exists and is a file, regardless of type (node, directory, socket, etc.). -f FILE - True if the FILE exists and is a regular file (not a directory or device). # case CHAR=a case $CHAR in [a-z]) echo "minúscules." ;; [A-Z]) echo "majúscules." ;; [0-9]) echo "Número." ;; *) echo "Caràcter especial." esac
bucles
for ((i = 0 ; i < 10 ; i++)) do echo $i done for i in {1..10} do echo $i done for i in /var/* do echo $i done num=1 while [ $num -le 10 ] do echo $num num=$(($num+1)) done until [ $num -gt 10 ] do echo $num num=$(($num+1)) done prime=(2 3 5 7 11 13 17 19 23 29) for i in "${prime[@]}" do echo $i done # break atura el bucle i segueix l'script # continue es salta la iteració en qüestió # bucles infinits for ((;;)) while [ true ]
funcions – a diferència d’altres llenguatges, no retorna valors. Retorna l’estat de sortida la última comanda (ho trobem a la varaible$?) on zero vol dir que ha anat bé i 1-255 que no. Es pot sobreescriure amb “return 0”. Return acaba la funció a l’instant. Els arguments es passen i igual que als scripts, però són independents.
#script.sh ... #!/bin/bash prova () { echo "$1 és el primer argument de prova()" echo "$2 és el segon argument de prova()" } echo "$1 és el primer argument de l'script." echo "$2 és el segon argument de l'script." fun Yes 7 ./script.sh Cool Cosa # executem l'script ... Cool és el primer argumento del script. Cosa és el segundo argumento del script. Yes és el primer argument de prova() 7 és el segundo argument de prova()
Podem definir variables locals dins la funció amb “local nom=’valor'”. Una variable local té prioritat sobre una global. A fins una funció podem modificar variables globals.