0. Índex
- Coses que se li passen a la majoria de la gent
- Estructura d'un script
- Imprimir a la pantalla
- Llegir l'INPUT de l'usuari
- Càlculs en Bash
- Condicions
- bucles
- Funcions
- Getops
1. Coses que se li passen a la majoria de la gent
/ Bin / bash o / bin / sh
Una de les primeres coses que fa la màquina a l'executar el nostre script és mirar amb quina shell ha de fer. En la majoria dels sistemes linux actuals / bin / sh és un enllaç a / Bin / bash, Però no sempre és així, per exemple en les distribucions que utilitzen BusyBox Porten Sh i normalment també porten xoc, Però si s'utilitza / bin / sh, No s'executarà amb Bash. Per això recomano utilitzar sempre / Bin / bash.
Unicode vs ASCII
Us heu preguntat per què no podeu utilitzar «» o «ñ» en els vostres scripts? O utilitzar accents? Pot arribar a ser bastant molest en scripts interactius. Això és perquè la codificació per defecte de Bash és ASCII, o el que és el mateix, el set de caràcters de l'anglès. Per canviar només hem de indicar-li al nostre script que volem utilitzar Unicode. Per això cal afegir una línia just després de l'intèrpret d'ordres:
# - * - ENCODING: UTF-8 - * -
Ull, és important que aquesta línia estigui a el principi de l'script.
Fer el script executable
És curiós la quantitat de gent que executa els scripts amb «$ Bash script.sh»En lloc de«$ ./script.sh»A la fi i al el cap és per a això que hem definit un intèrpret d'ordres.
Per afegir permisos d'execució cal executar:
suo + x script.sh
BIN = "carpeta on tinguem els scripts" PATH = "$ BIN $ PATH"
2. Estructura d'un script
- Capçalera
- Definició de variables globals
- Ajuda
- Funcions
- Cos principal
La capçalera és on s'indica quin shell volem utilitzar i la codificació. L'avantatge de les funcions és reutilitzar codi que es repeteix escrivint una sola vegada i fer més fàcil l'enteniment de l'script, per codi que supera les 100 línies és molt útil.
Per poder utilitzar funcions, aquestes han d'estar definides amb abans de el cos principal del nostre script. I si volem utilitzar variables a nivell global de tot el nostre script, tant en el cos principal com a les funcions, hem de definir-les a el principi de tot, just després de la capçalera.
Finalment, és de bona pràctica escriure una funció d'ajuda per quan el nostre script s'executi malament o amb mals paràmetres. Òbviament, és aquests casos volem sortir de l'script immediatament, sense llegir les funcions. Per això podem utilitzar:
function help () {echo "" "El nostre text d'ajuda bé formatat." "" exit if [[-z $ 1 || $ 1 == "-h" || $ 1 == "--help"]]; then help fi
Si afegim «exit» a la funció d'ajuda, sortirem de l'script cada vegada que executem ajuda, per exemple després de missatges d'errors, etc. Ens estalviem un parell de línies de codi.
La condició indica mostrar ajuda en pantalla i sortir si s'executa l'script sense paràmetres o si s'indica -h / -help. Si us fixeu aquest és el comportament estàndard de la majoria de programes linux.
3. Imprimeix a pantalla
Ha 2 comandaments principals per imprimir en pantalla en bash: «trobo»i«imprimirf«. Els dos són igual de ràpids i els dos formen part de bash. La principal diferència per a un principiant és que trobo afegeix un salt de línia a al final, mentre que «imprimirf»No ho fa.
Trobo està molt bé i és el que fa servir la majoria de la gent, però quan es llegeixen l'INPUT de l'usuari, o quan es volen imprimir variables tretes d'arxius mitjançant processat de text, poden passar coses rares. Normalment es solucionen fàcilment, tan fàcil com canviar les dobles cometes a simples o viceversa, o treure les referències a variables fora de les cometes. «ressò»Fa coses rares també depenent de com s'ha compilat, si utilitzem sempre Ubuntu o sempre Fedora, no ens afecta, però si canviem de distribució si.
Per això utilitzo «imprimirf«, Que no em dóna mals de cap ia més es comporta més com el«imprimirf»De C o el«imprimir»De Python, això és molt important si algun dia voleu portar el vostre script a un altre llenguatge de programació.
4. Llegir l'INPUT de l'usuari
Tot el que escrivim després de el nom del nostre script i abans de donar-li a la tecla de retorn queda automàticament guardat en unes variables especials. Aquestes variables són de tipus $ X on la X és un nombre.
«$0»Indica el nom del nostre script i des de«$1»Fins a l'infinit són variables tot el que hem escrit després. Per exemple:
cat << EOF >> test.sh #! / bin / bash # - * - ENCODING: UTF-8 - * - printf "\ $ 0 = $ 0 \ n" printf "\ $ 1 = $ 1 \ n" printf "\ $ 2 = $ 2 \ n "EOF chmod + x script.sh ./script.sh meu fitxer.txt
Creem un script de prova, ho fem executable i l'executem amb 2 paràmetres. Obtenim la sortida en pantalla de:
$ 0 = ./script.sh $ 1 = la meva $ 2 = fitxer.txt
Utilitzant cometes podríem haver passat «el meu fitxer.txt" a "$ 1».
També podem llegir l'INPUT d'un usuari amb la comanda «read», indicant directament la variable on vulguem guardar el paràmetre. Per exemple:
printf "Com et dius? \ n" read NOM printf "Hola, $ NOM. \ n"
5. Càlculs en Bash
Per això podem utilitzar «expressar«, Sempre que no necessitem fer cáclculos complexos. Cal destacar dues coses, la primera és que «expressar»Només admet nombres enters, la segona és que la divisió retorna el resultat sencer, per veure la resta podem utilitzar«%".
Normalment voldrem assignar el resultat d'expr a una variable. Això ho podrem fer de dues formes:
Var2 = `expr $ VAR1 / 10` var2 = $ (expr $ VAR1 / 100)
També es pot obviar «expressar»Utilitzant doble parèntesi:
Var2 = $ (($ VAR1 / 100))
6. condicions
S'ha escrit ja d'una manera molt extensa sobre «if","else","elif»I les condicions. Podeu llegir sobre això a:
- Programant en Bash: part 1
- Bash: condicions if, then, else
- Comprovar si un arxiu o carpeta existeix o no i mes amb un cicle if
- Programant en Bash: part 2
Només vull destacar la diferència entre l'ús de simples claudàtors, «[]«, I dobles claudàtors,«[[]]«, Per a la condicions. Amb dobles claudàtors podem utilitzar condicions addicionals:
- «&&»Per i
- «||»Per o
Per utilitzar «&&»i«||»Amb simples claudàtors caldria separar cada part entre claudàtors separats. L'exemple utilitzat per la part de l'script que mira si cal executar ajuda quedaria:
if [-z "$ 1"] || [ "$ 1" == "-h"] || [ "$ 1" == "--help"]]; then help fi
També ens evita el haver d'escriure els noms de variables dins de cometes per prevenir errors. Per exemple:
if [$ 1 = 1]; then printf "El paràmetre és igual a 1."; fi if [ "$ 1" = 1]; then printf "El paràmetre és igual a 1."; fi if [[$ 1 = 1]]; then printf "El paràmetre és igual a 1."; fi
Si s'executa script.sh sense cap paràmetre, el primer cas donaria un error:
bash: [: =: s'esperava un operador unari
Del que no s'ha parlat és de «cas«, Que s'utilitza per simplificar«if«. Comencem pel principi, quan no tenim cap «if»S'executarà tot el codi. Si afegim una condició «if»Tindrem dos casos, un en què s'executa el bloc de codi que està dins de l'«if»I l'altre cas on no s'executa aquest bloc.
Si afegim un «else«, També tindrem dues casos, però aquests dos casos són diferents als anteriors. Perquè ara hi haurà dos blocs de codi condicionals, A i B, i un bloc C, que és la resta de el programa. S'executarà A o B, i C. En el cas anterior era A i C o només C.
Per evitar escriure condicions «if / else»Dins«else»I simplificar la lectura d'el codi, es va crear«elif«. Quan tenim moltes condicions que depenen de l'anterior, per exemple rang de nombres o de l'tipus:
VAR1 = $ 1 if [[$ VAR1 = 1]]; then printf "1 \ n" elif [[$ VAR1 = 2]]; then printf "2 \ n" elif [[$ VAR1 = 3]]; then printf "3 \ n" else printf "cap \ n" fi
En el cas de l'últim «elif»Es llegiran moltes condicions. Amb casi s'agilitza aquest procés:
VAR1 = $ 1 casi $ VAR in 1) printf "1 \ n" ;; 2) printf "2 \ n" ;; 3 | 4) printf "3 o 4, depèn \ n" ;; *) Printf "cap \ n" ;; esac
Es llegirà una variable, en aquest cas VAR1, i es mirarà si equival a algun dels casos, si no, s'executarà el cas per defecte «*». Els dobles punt i coma equivalen a «trencar«, Li indiquen a«cas»Que ha d'acabar.
7. Bucles
Són molt pocs els bucles a saber-se en qualsevol llenguatge de programació. En Bash són «mentre","fins»i«for«. S'ha escrit ja al blog sobre aquests:
Hi ha dos tipus de bucles «for«, Els que són de l'tipus«$ For VAR in loquesea»I el que són de l'tipus C«$ For ((I = 0; I <= 10; I ++))«. El segon tipus de bucles «for»Són molt útils, té 3 parts en l'inici de l'bucle:
- Declaració i iniciació de variables (En aquest cas una variable auxiliar «I = 0»).
- Condició d'execució (fins que I sigui menor o igual que 10).
- Increment de la variable auxiliar
Al meu entendre és el bucle més potent de tots. Un exemple, que imprimeix tots els números des del 0 fins al 10, ambdós inclosos:
#! / Bin / bash for ((I = 0; I <= 10; I ++)); do printf "$ I \ n" done
8. Funcions
Hi ha algunes coses que Bash no ens permet fer, o si? En un primer cop d'ull, les funcions de bash impedeixen fer 3 coses: declarar variables locals en les funcions, passar-li paràmetres a les funcions i retornar paràmetres. Tot té solució.
No fer res per l'estil de:
#! / Bin / bash VAR = 1 printc "$ VAR \ n" function hola () {VAR = 2 printf "$ VAR \ n"} hola printf "$ VAR \ n"
Això imprimeix en pantalla 1, 2 i 2.
Per declarar variables locals hi afegir «local»Quan es declara:
#! / Bin / bash VAR = 1 printf "$ VAR1 \ n" function foo () {local VAR1 = 2 printf "$ VAR1 \ n"} printf "$ VAR1 \ n" foo printf "$ VAR1 \ n"
Això imprimeix en pantalla 1, 1, 2, 1.
Com se li passen paràmetres a una funció?
#! / Bin / bash # - * - ENCODING: UTF-8 - * - function hola () {printf "Hola $ 1 \ n"}
printf «Com et dius? \ n»
read VAR1
hola $ VAR1
Com es tornen paràmetres?
#! / Bin / bash # - * - ENCODING: UTF-8 - * - function hola () {printf "Hola holita"} printf "Com et dius? \ N" read VAR1 VAR1 = $ (hola) # AQUI ESTÀ printf "$ VAR1 $ var2 \ n"
Com veieu això té dues pegues, només es pot tornar un paràmetre, que pot ser un vector 😀, i si es vol tornar un paràmetre, ja no es pot imprimir en pantalla des d'aquesta funció.
9. Getops
Una de les últimes coses de Bash que cal conèixer per crear scripts complexos és «getops«. Serveix per passar opcions a l'script sense importar l'ordre. L'única pega és que només afecta opcions curtes:
#! / Bin / bash # - * - ENCODING: UTF-8 - * - VARC = 0 function help () {printf "Missatge d'ajuda \ n" exit} if [[-z $ 1]]; then help fi while getopts: ha: b: c OPT; do casi $ OPT in h) help ;; :) help ;; a) VARA = $ OPTARG ;; b) VARB = $ OPTARG ;; c) VARC = 1 ;; \?) Help ;; esac done # Bloc principal de l'script que # fa coses amb VARA, VARB i VARC
«Getopts»Llegeix les opcions una a una, per això es necessita d'un bucle.
Hi ha 2 tipus d'opcions que es poden passar usant «getopts":
- Els paràmetres anomenats flags, en aquest cas -co -h. S'especifiquen amb la lletra que vulguem utilitzar. Són com a variables booleanes, «veritable»(Estan) o«false»(No hi són).
- Paràmetres amb arguments associats, -a Cualquiercosa, -b Cualquiercosa. S'especifiquen amb la lletra que vulguem amb dos punts a continuació. L'argument és guardat en OPTARG (aquest nom és inalterable).
Què fa aquest script?
Mostra el missatge d'ajuda quan no es passa cap opció, quan es passa el paràmetre «-h», quan es passa un paràmetre no vàlid (per exemple «-x», això ho fa «\?») O quan es passa un paràmetre vàlid sense argument ( «:»). En la resta dels casos guarda la presència de «-c» com un 1 en VARC, i els valors passats amb «-a» i «-b» a VARA i VARB.
MAGISTRAL. no dic més U_U
Hola molt bon article.
Escolta vas posar per donar permisos suo + x en comptes de chmod + x
$ Sudo chmod + x script.sh
(Per ser més exactes, jeje)
Ah, Felicitats i gràcies!
Molt bon post, la veritat et felicito, segueix així, Salutacions
I si vols que l'script sigui visible quan s'executa, pas a pas, veient per exemple com es comporten variables, condicions i tooodo, podeu fer servir:
sh -x script
Salutacions
Tros de tut. Excel·lent i molt ben explicat.
Gràcies.
Excel·lent post sobre el tema 😉
Molt interessant i importantíssim gràcies per la informació ....
SALUTACIONS !!!
Gràcies a tots per les vostres felicitacions, pel que fa a la comanda Miguel, no em deixa modificar l'entrada una vegada que està publicada. Ho haurà de fer ILAV m'imagino.
Molt bones!
primer de tot volia felicitar-vos pel post, l'he trobat fàcil d'entendre i realment ajuda a seguir les pautes per programar bé en bash, sobretot per a gent que està començant a programar.
No obstant això he trobat un parell de detalls dels quals crec que haurien de ser corregits.
Primer: en l'apartat «2. ESTRUCTURA D'UN SCRIPT »la funció no està tancada, la qual cosa donarà problemes a l'hora d'executar-la en un script.
La solució seria afegir-li un tancament de clau just després de la comanda 'exit'.
Segon: en l'apartat «4. LLEGIR EL INPUT DE L'USUARI »afirmeu que els paràmetres que pot introduir l'usuari van des de $ 0 fins a l'infinit, però« bash »només interpretarà des del $ 0 fins al $ 9, ja que $ 10 seria igual a $ 1 + 0.
Per solucionar aquest problema, es podria o bé utilitzar la comanda «shift» per anar prenent les variables següents. O bé especificar la variable entre claus «$ {10}», perquè bash prengui els valors junts, no com $ 1 + 0.
Sense més, una salutació!
Gràcies pel teu comentari. Es em va passar totalment explicar l'ús correcte de exit, tant en l'script com en les funcions. Pel que fa a $ {10} no he llegat a tant, així que no m'he topat amb aquest problema, és bo saber que hi ha una solució per això (ja he titllat la nova cosa apresa avui 😀).
Moltes gràcies per l'article! Algunes coses de les que esmentes em faltaven aclarir. Per exemple, getops.
A la part de sortides per pantalla, et va faltar esmentar el cat que després esmentes ...
cat <
***************************************
* AQUESTA FORMA ÉS MOLT EXPRESSIVA *
***************************************
EOF
En el teu exemple:
cat << EOF >> test.sh
Cal esmentar dues coses ... >> és 'append' o sigui, que si repeteixes el mateix comandament, tindràs tot el guió per duplicat ... Hauries de fer servir solament una ...
cat << EOF> script.sh
Si, també s'havia de dir script.sh
Després, en
if [-z "$ 1"] || [ «$ 1» == «-h»] || [ «$ 1» == «-help»]]; then
ajuda
fi
Crec que hauria d'escriure ...
if [[-z "$ 1"] || [ «$ 1» == «-h»] || [ «$ 1» == «-help»]]; then
...
Hi ha molt més per descobrir de BASH.
Podries titular-«BÁSHICOS»? 🙂
Per exemple, els 'emprovadors' de paràmetres com -z per saber si estan buits, o -f per saber si hi ha com a arxiu.
Novament, gràcies pel teu esforç.
alberto
Un molt bon tutorial de bash script!
-- ENCODING: UTF-8 --
És la primera vegada que veig aquesta línia per establir la codificació de caràcters en un script Bash. Em sembla més pròpia de Python que de Bash. De debò que és necessària? He buscat alguna referència a Google però no trobo res, teniu a mà algun enllaç que parli sobre aquest assumpte? En concret sobre la idoneïtat d'aquesta línia.
Al meu entendre, per escriure scripts en Bash usant UTF-8, únicament cal guardar l'arxiu de text com a tal (sense BOM) i tenir certes variables d'entorn, (LANG i LC_ *), correctament establertes.
Després, òbviament, cal que els ordres executades estiguin preparats per codificacions diferents de ASCII. Per exemple, si volem passar a majúscules, això sembla no funcionar:
«Tiro áéíóú | tr az AZ »
o:
«Tiro áéíóú | tr [: lower:] [: upper:] »
i és millor fer servir:
«Tiro áéíóú | awk '{print ToUpper ($ 0)}' ».
El de l' «codificació»S'ha esmentat en aquest bloc amb anterioritat:
Bash: com fer un script executable
Script útil post instalacion
Que algú em corregeixi, però aquesta línia de encoding (# -- ENCODING: UTF-8 --) NO té res a veure amb bash o el shell: és una línia de comentari (comença per #) i serveix per indicar-li a l'EDITOR que usem per escriure el script (vim, emacs ...) la codificació de l'arxiu.
De fet, bash no veu aquesta línia, perquè és una línia de comentari.
Excel·lent tutorial, com sysadmin saber Scriptear en Bash és fonamental, et serveix per a tot.
Molt però molt bo!
Salutacions!
Per si a algú li és d'utilitat, aquí diversos usos i exemples per crear els seus propis Scripts: https://github.com/reduardo7/hsabx
Molt bo. Noves coses per afegir als meus scrips. El de encodig i el de printf no el tenia.
Gràcies !!!
Moooolt bon article! Aquest me'l guardo per favorits, estaria bé corregir el que està malament i fins i tot expandir-amb més contingut. Un aplaudiment per tota aquesta info !!!!