Teoria de Bash

/ Bin / bash

0. Índex

  1. Coses que se li passen a la majoria de la gent
  2. Estructura d'un script
  3. Imprimir a la pantalla
  4. Llegir l'INPUT de l'usuari
  5. Càlculs en Bash
  6. Condicions
  7. bucles
  8. Funcions
  9. 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
Si el nostre script és executable, el podem afegir al nostre PATH i fer que sigui executable des de qualsevol lloc / carpeta del nostre equip. Per això cal afegir ja sigui a l'.bashrc del nostre usuari o / etc / bashrc la línia
BIN = "carpeta on tinguem els scripts" PATH = "$ BIN $ PATH"
És una norma de Bash escriure els noms de variables tot en majúscules. Molta gent no segueix aquesta norma, però per guions llargs s'agraeix perquè els fan molt més llegibles

2. Estructura d'un script

  1. Capçalera
  2. Definició de variables globals
  3. Ajuda
  4. Funcions
  5. 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.

L'ús de les 3 cometes amb trobo permet utilitzar salts de línia sense sortir de l'missatge a mostrar per fet. Per a missatges multilínia és molt mes còmode utilitzar trobo una sola vegada.

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ó.

Per a una discussió més extensa podeu visitar aquesta pregunta de Unix & Linux en Stack Exchange.

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"
Ull amb l'assignació de variables. «$ VAR = contingut» produirà un error, no es poden deixar espais entre el signe igual, el nom de la variable i el contingut. L'ús correcte és «VAR = contingut»

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))
Per a una major explicació de «expressar»O una alternativa que utilitzi nombres enters, podeu mirar aquesta entrada de KZKG ^ Gaara.

6. condicions

S'ha escrit ja d'una manera molt extensa sobre «if","else","elif»I les condicions. Podeu llegir sobre això a:

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
En Bash «=» i «==» s'interpreten tots dos de la mateixa manera. Això no passa en altres llenguatges de programació on «=» s'utilitza només per assignar variables.

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.

«cas»Es pot utilitzar també com una successió de«if«, Per a això cal utilitzar« ;; & »(continuar) en lloc de« ;; » (Parar).

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ó.

Podeu trobar més coses de funcions a [url=https://blog.desdelinux.net/programando-en-bash-parte-3/]aquest article d'Usemoslinux[/url].

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).
Els dobles punts inicials són per a no mostrar errors.

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.


Deixa el teu comentari

La seva adreça de correu electrònic no es publicarà. Els camps obligatoris estan marcats amb *

*

*

  1. Responsable de les dades: Miguel Ángel Gatón
  2. Finalitat de les dades: Controlar l'SPAM, gestió de comentaris.
  3. Legitimació: El teu consentiment
  4. Comunicació de les dades: No es comunicaran les dades a tercers excepte per obligació legal.
  5. Emmagatzematge de les dades: Base de dades allotjada en Occentus Networks (UE)
  6. Drets: En qualsevol moment pots limitar, recuperar i esborrar la teva informació.

  1.   ILAV va dir

    MAGISTRAL. no dic més U_U

  2.   Miguel va dir

    Hola molt bon article.
    Escolta vas posar per donar permisos suo + x en comptes de chmod + x

    1.    Henry va dir

      $ Sudo chmod + x script.sh
      (Per ser més exactes, jeje)

      Ah, Felicitats i gràcies!

  3.   firecold va dir

    Molt bon post, la veritat et felicito, segueix així, Salutacions

  4.   Gustavo va dir

    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

  5.   allà va dir

    Tros de tut. Excel·lent i molt ben explicat.
    Gràcies.

  6.   Gabriel va dir

    Excel·lent post sobre el tema 😉

  7.   Mario Guillermo Zavala Silva va dir

    Molt interessant i importantíssim gràcies per la informació ....
    SALUTACIONS !!!

  8.   Notfrombrooklyn va dir

    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.

  9.   Adrián va dir

    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ó!

    1.    Notfrombrooklyn va dir

      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 😀).

  10.   chanio va dir

    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

  11.   clow_eriol va dir

    Un molt bon tutorial de bash script!

  12.   OCZ va dir

    -- 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)}' ».

    1.    Notfrombrooklyn va dir

      El de l' «codificació»S'ha esmentat en aquest bloc amb anterioritat:

      Bash: com fer un script executable
      Script útil post instalacion

    2.    borriquitocomotu va dir

      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.

  13.   Jorge-1987 va dir

    Excel·lent tutorial, com sysadmin saber Scriptear en Bash és fonamental, et serveix per a tot.

    Molt però molt bo!

    Salutacions!

  14.   Eduardo Cuomo va dir

    Per si a algú li és d'utilitat, aquí diversos usos i exemples per crear els seus propis Scripts: https://github.com/reduardo7/hsabx

  15.   Negre Lito va dir

    Molt bo. Noves coses per afegir als meus scrips. El de encodig i el de printf no el tenia.
    Gràcies !!!

  16.   xxxtonixxx va dir

    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 !!!!