Scrierea unui scripturi Shell de la zero

Scrierea scripturilor de coajă poate fi destul de descurajantă, în primul rând pentru că shell-ul nu este cel mai prietenos dintre limbile de utilizat. Cu toate acestea, sper să vă arăt în acest tutorial că scripting-ul shell-ului nu este de fapt atât de dur sau de înfricoșător cum v-ați aștepta.

Pentru acest tutorial, vom scrie un script care face puțin mai ușor procesul de utilizare a cadrului de testare Jasmine. De fapt, nu aș folosi astăzi acest script; Aș folosi Grunt.js sau ceva similar. Cu toate acestea, am scris acest scenariu înainte ca Grunt să fi fost în jur și am constatat că scrierea sa dovedit a fi o modalitate excelentă de a se simți mai confortabil cu scriptingul shell-ului, de aceea îl folosim.

O notă: acest tutorial este asociat în mod liber cu cursul Tuts + Premium, "Advanced Techniques Line Command". Pentru a afla mai multe despre ceva mai mult din acest tutorial, stați la acord pentru lansarea acestui curs. În continuare, în acest tutorial, va fi denumit "cursul".

Deci, scenariul nostru, pe care îl numesc jazz, vor avea patru caracteristici principale:

  • Acesta va descărca Jasmine de pe web, dezarhivați-l și ștergeți exemplul de cod.
  • Acesta va crea fișiere JavaScript și fișierele de spec. Asociate și le va pre-completa cu un cod de șablon.
  • Acesta va deschide testele în browser.
  • Acesta va afișa textul de ajutor, care conturează cele de mai sus.

Să începem cu fișierul de script.


Pasul 1 - Crearea fișierului

Scrierea unui script shell este utilă numai dacă îl puteți folosi de la terminal; pentru a putea utiliza scripturile personalizate pe terminal, trebuie să le puneți într-un director care se află în terminalul dvs. CALE variabilă (vă puteți vedea CALE variabilă prin rulare echo $ PATH). Am creat o ~ / Bin dosar (în cazul în care ~ este directorul de acasă) pe computerul meu și acolo îmi place să păstrez scripturi personalizate (dacă faceți același lucru, va trebui să îl adăugați pe calea ta). Deci, trebuie doar să creați un fișier, numit jazz, și puneți-l în dosarul dvs..

Desigur, va trebui, de asemenea, să facem fișierul executabil; în caz contrar, nu vom putea să o executați. Putem face acest lucru executând următoarea comandă:

 chmod + x jazz

Acum că putem executa scenariul, să adăugăm o parte foarte importantă. Toate scripturile de shell ar trebui să înceapă cu un shebang). După cum afirmă Wikipedia, aceasta ar trebui să fie prima linie a scenariului; afirmă ce interpret sau coajă trebuie să fie rulat cu acest script. Vom folosi o cochilie de bază, standard:

 #! / Bin / sh

Bine, cu tot ceea ce am creat, suntem gata să începem să scriem codul real.


Pasul 2 - Prezentarea fluxului scriptului

Anterior, am subliniat care ar trebui să fie diferitele caracteristici ale scriptului nostru de shell. Dar cum va ști scriptul ce caracteristică va funcționa? Vom folosi o combinație a unui parametru shell și a unei instrucțiuni de caz. Când rulați scriptul din linia de comandă, vom folosi o subcomandă, după cum urmează:

 jazz init jazz creează ajutorul jazz-ului SomeFile jazz

Acest lucru ar trebui să pară familiar, mai ales dacă ați folosit Git:

 git init git status

Pe baza acelui prim parametru (init, crea, alerga, Ajutor), declarația cazului nostru va decide ce să fugă. Cu toate acestea, avem nevoie de un caz implicit: ce se întâmplă dacă nu este dat nici un prim parametru sau primim un prim parametru nerecunoscut? În aceste cazuri, vom afișa textul de ajutor. Deci sa începem!


Pasul 3 - Scrierea textului de ajutor

Începem cu dacă afirmația că verifică primul parametru:

 dacă [$ 1] atunci # face altceva # arată fiți de ajutor fi

S-ar putea să fii puțin confuză la început, pentru că eo coajă dacă declarația este destul de diferită de cea a limbajului de programare "regulat" dacă afirmație. Pentru a înțelege mai bine acest lucru, vizionați ecranul pe declarații condiționate din curs. Acest cod verifică prezența unui prim parametru ($ de 1); dacă este acolo, vom executa atunci cod; altfel, vom afișa textul de ajutor.

Este o idee bună să împachetați imprimarea textului de ajutor într-o funcție, deoarece trebuie să o numim mai mult decât o dată. Trebuie să definim funcția înainte de a fi sunată, așa că o vom pune în partea de sus. Îmi place asta, pentru că acum, de îndată ce deschid fișierul, văd documentația pentru script, care poate fi un memento util atunci când se întoarce la codul pe care nu l-ați văzut de ceva timp. Fără alte cuvinte, iată Ajutor funcţie:

 help function () echo "jazz - Un script simplu care face folosirea cadrului de testare Jasmine intr-un proiect standalone un pic mai simplu." echo "echo" jazz init - include iasomie în proiect "; echo" jazz create FunctionName - creează ./src/FunctionName.js ./spec/FunctionNameSpec.js "; echo" jazz execută teste în browser ";

Acum, înlocuiți asta # arată ajutor cu o convorbire către Ajutor funcţie.

 altceva ajuta fi

Pasul 4 - Scrierea declarației de caz

Dacă există un prim parametru, trebuie să ne dăm seama care este. Pentru aceasta, folosim a caz afirmație:

 cazul "$ 1" în init) ;; crea) ;; alerga) ;; *) Ajutor ;; ESAC

Transmitem primul parametru la caz afirmație; apoi, ar trebui să se potrivească cu unul dintre cele patru lucruri: "init", "create", "run" sau caracterele noastre wild, caz implicit. Observați că nu avem un caz explicit de "ajutor": acesta este doar cazul nostru implicit. Acest lucru funcționează, deoarece orice altceva decât "init", "create" și "run" nu sunt comenzi pe care le recunoaștem, deci trebuie să obțineți textul de ajutor.

Acum suntem gata să scriem codul funcțional și vom începe cu asta jazz init.


Pasul 5 - Pregătirea iasomiei cu jazz init

Toate codurile pe care le scriem aici vor intra în interiorul nostru init) cazul, din declarația de mai sus. Primul pas este de a descărca de fapt versiunea stand-alone a Jasmine, care vine într-un fișier zip:

 ecou "Descărcarea Jasmine ..." curl -sO $ JASMINE_LINK

Mai întâi un ecou un mic mesaj și apoi vom folosi răsuci pentru a descărca zipul. s steagul face silențios (fără ieșire) și O steagul salvează conținutul zipului într-un fișier (în caz contrar, acesta ar fi trimis la standard). Dar ce e cu asta? $ JASMINE_LINK variabil? Ei bine, ai putea pune legătura reală cu fișierul zip acolo, dar prefer să o pun într-o variabilă din două motive: în primul rând, ne împiedică să repetăm ​​o parte din cale, așa cum veți vedea într-un minut. În al doilea rând, cu această variabilă în partea de sus a fișierului, este ușor să schimbăm versiunea de Jasmine pe care o folosim: trebuie doar să schimbi acea variabilă. Iată declarația variabilă (l-am pus în afara dacă declarație, în partea de sus):

 JASMIME_LINK = "http://cloud.github.com/downloads/pivotal/jasmine/jasmine-standalone-1.3.1.zip"

Amintiți-vă că nu există spații în jurul semnalului egal în acea linie.

Acum, că avem fișierul zip, îl putem dezarhiva și pregăti conținutul:

 unzip -q nume de bază $ JASMINE_LINK rm -rf nume de bază $ JASMINE_LINK src / * .JS spec / *. js

În două dintre aceste linii, folosim nume de bază $ JASMINE_LINK; basename comanda reduce doar o cale către numele de bază: așa calea / catre / file.zip devine justa file.zip. Acest lucru ne permite să folosim acest lucru $ JASMINE_LINK variabilă pentru a face referire la fișierul zip local.

După ce dezarhivez, vom șterge fișierul zip, precum și toate fișierele JavaScript din src și spec directoare. Acestea sunt fișierele de probă cu care vine Jasmine și nu avem nevoie de ele.

Apoi, avem o problemă cu Mac numai pentru a face față. În mod implicit, atunci când descărcați ceva de pe Internet pe un Mac, când încercați să îl executați pentru prima dată, vi se va cere să confirmați că doriți să îl rulați. Acest lucru se datorează atributului extins com.apple.quarantine că Apple pune pe dosar. Trebuie să eliminăm acest atribut.

 dacă xattr> / dev / null && ["xattr SpecRunner.html"=" com.apple.quarantine "] apoi xattr -d com.apple.quarantine SpecRunner.html fi

Începem prin a verifica prezența xattr deoarece nu există pe unele sisteme Unix (nu sunt sigur, dar poate fi un program numai pentru Mac). Dacă ați urmărit difuzarea cursului pe condiționate, veți ști că putem transmite orice comandă dacă; dacă are un statut de ieșire de orice altceva decât 0, este fals. Dacă care găsește xattr comanda, va ieși cu 0; în caz contrar, va ieși cu 1. In orice caz, care va afișa o anumită ieșire; putem să ne păstrăm acest lucru prin a ne redirecționa / Dev / null (acesta este un fișier special care elimină toate datele scrise).

Acest dublu ampersand este un boolean AND; este acolo pentru a doua condiție pe care vrem să o verificăm. Asta este, nu SpecRunner.html aveți acel atribut? Putem pur și simplu rula xattr comanda pe fișier și comparați ieșirea cu șirul pe care îl așteptăm. (Nu ne putem aștepta ca fișierul să aibă atributul, pentru că de fapt puteți dezactiva această caracteristică în Mac OS X și vom obține o eroare atunci când încercăm să o eliminăm dacă fișierul nu are atributul).

Astfel, dacă xattr este găsit și fișierul are atributul, îl vom elimina, cu d (pentru ștergere). Destul de simplu, corect?

Ultimul pas este să editați SpecRunner.html. În prezent, conține etichete de scripturi pentru exemplele de fișiere JavaScript pe care le-am șters; ar trebui să ștergem și aceste etichete pentru scripturi. Se întâmplă să știu că acele tag-uri scanează linii de la 12 la 18 în fișiere. Deci, putem folosi editorul fluxului sed pentru a șterge aceste linii:

 sed-i "" 12, 18d "SpecRunner.html ecou" Jasmine inițializată! "

eu pavilionul spune sed pentru a edita fișierul în loc sau pentru a salva ieșirea din comandă în același fișier în care am trecut; șirul gol după steag înseamnă că nu vrem sed să facem o copie de rezervă pentru noi; dacă doriți acest lucru, ați putea pune o extensie de fișier în acel șir (cum ar fi .Bak, a obține SpecRunner.html.bak).

În cele din urmă, vom lăsa utilizatorul să știe că Jasmine a fost inițializată. Și asta e pentru noi jazz init comanda.


Pasul 6 - Crearea fișierelor cu jazz crea

În continuare, vom permite utilizatorilor noștri să creeze fișiere JavaScript și fișierele de spec. Această porțiune a codului va merge în secțiunea "creați" din caz declarație pe care am scris-o mai devreme.

 în cazul în care [$ 2], atunci # creați alte fișiere echo ", vă rugăm să includeți un nume pentru fișierul" fi

Atunci când se utilizează jazz crea, trebuie să includeți un nume pentru fișier ca al doilea parametru: jazz create View, de exemplu. Vom folosi acest lucru pentru a crea src / View.js și spec / ViewSpec.js. Deci, dacă nu există un al doilea parametru, vom reaminti utilizatorului să adauge unul.

Dacă există un nume de fișier, vom începe prin crearea celor două fișiere (în interiorul atunci partea de mai sus):

 echo "funcția $ 2 () \ n \ n"> src / $ 2.js echo "descrie ('$ 2', funcția () \ n \ n > spec / $ 2Spec.js

Desigur, poți pune tot ce vrei în tine src fişier. Fac ceva de bază aici; asa de jazz create View va crea src / View.js cu asta:

 funcția View () 

Ați putea să o înlocuiți mai întâi ecou line cu aceasta:

 echo "var $ 2 = (funcția () \ n \ forma $ 2Prototype = \ n \ n \ t; \ n \ t \ shape o = Object.create ($ 2Prototype); \ n \ t \ t \ textend (o, attrs); \ n \ t \ t \ treturn o; \ n \ t \ t \ n \ t; \ n ());“ > src / $ 2.js

Și apoi jazz create View va avea ca rezultat:

 var View = (functie () var ViewPrototype = ; return create: function (attrs) var o = Object.create (ViewPrototype); ;

Deci, într-adevăr, imaginația ta este limita. Desigur, veți dori ca fișierul spec să fie codul standard Jasmine, care este ceea ce am mai sus; dar puteți schimba tot ce vă place și dumneavoastră.

Următorul pas este să adăugați etichetele de script pentru aceste fișiere SpecRunner.html. La început, acest lucru ar putea părea complicat: cum putem adăuga linii la mijlocul unui fișier programat? Încă o dată, este sed care face treaba.

 sed-i "" "11a \\ \\  "SpecRunner.html

Începem exact așa cum am procedat înainte: editați în loc fără o copie de rezervă. Apoi comanda noastră: la linia 11, dorim să adăugăm cele două linii următoare. Este important să scăpați de cele două linii noi, astfel încât acestea să apară în text. După cum puteți vedea, acest lucru introduce doar acele două etichete scripturi, exact ceea ce avem nevoie pentru acest pas.

Putem încheia cu o anumită ieșire:

 echo "\ t- spec / $ 2Spec.js" echo "Editat:" echo "\ t- SpecRunner.html"

Si asta e jazz crea!


Pasul 7 - Rularea specificațiilor cu jazz run

Ultimul pas este de a rula efectiv testele. Aceasta înseamnă deschiderea SpecRunner.html fișier într-un browser. E un fel de avertisment aici. Pe Mac OS X, putem folosi deschis comanda pentru a deschide un fișier în programul său implicit; acest lucru nu va funcționa pe niciun alt sistem de operare, dar așa procedez și eu aici. Din păcate, nu există o cale reală de tip cross-platform pentru a face acest lucru, despre care știu. Dacă utilizați acest script sub Cygwin pe Windows, puteți utiliza cygstart in locul deschis; în caz contrar, încercați să googling "browser-ul dvs. [OS] browser-ul deschis" și să vedeți ce ați venit. Din păcate, unele versiuni de Linux (cel puțin Ubuntu, din experiența mea) au un deschis comanda care este pentru ceva complet diferit. Cu toate acestea, kilometrajul dvs. cu următoarele poate varia.

dacă ["'care se deschide" "=" / usr / bin / open "], atunci deschideți SpecRunner.html altceva echo" Vă rugăm să deschideți SpecRunner.html în browser "

Până acum, știi exact ce face asta: dacă avem deschis, vom deschide SpecRunner.html, în caz contrar, vom imprima un mesaj care îi spune utilizatorului să deschidă fișierul în browser.

Inițial, asta dacă starea a arătat astfel:

dacă deschideți> / dev / null

Așa cum am făcut-o xattr, tocmai a verificat existența deschis; totuși, de când am aflat că există un altul deschis (chiar și pe serverul meu Ubuntu, care nu poate deschide nici un browser!), m-am gândit că ar fi mai bine să comparăm calea deschis program, deoarece Linux este la / Bin / deschis (din nou, cel puțin pe serverul Ubuntu).

Toate aceste cuvinte suplimentare despre deschis ar putea suna ca o scuză pentru lipsa mea de o soluție bună, arată de fapt ceva important în linia de comandă. Nu confundați înțelegerea terminalului cu înțelegerea configurației unui computer. Acest tutorial și cursul asociat te-au învățat puțin mai multe despre shell-ul Bash (și shell-ul Z), dar asta nu înseamnă că fiecare computer pe care îl folosești va fi configurat la fel; există multe moduri de a instala comenzi noi (sau diferite versiuni de comenzi), precum și de a elimina comenzi. Caveat dezvoltator.

Ei bine, asta e tot scenariul! Aici este din nou, toți împreună:

 #! / bin / sh function help () echo "jazz - Un script simplu care face folosirea cadrului de testare Jasmine intr-un proiect standalone un pic mai simplu." echo "" echo "jazz init - include iasomie în proiect"; echo "jazz createNameName - creează ./src/FunctionName.js ./spec/FunctionNameSpec.js"; echo "jazz run - rulează teste în browser";  JASMIME_LINK = "http://cloud.github.com/downloads/pivotal/jasmine/jasmine-standalone-1.3.1.zip" dacă [$ 1] apoi "$ 1" în init) echo "Descărcarea Jasmine ..." curl - sS $ JASMIME_LINK dezarhivează -q 'baze de date $ JASMIME_LINK' rm 'baze de date $ JASMIME_LINK' src / *. js spec / *. js dacă ce xattr> / dev / null && ["'xattr SpecRunner.html'" = .cratantine "] apoi xattr -d com.apple.quarantine SpecRunner.html fi sed -i" "" 12,18d "SpecRunner.html echo" Jasmine inițializată! " ;; crează) dacă [$ 2] apoi echo "funcția $ 2 () \ n \ n"> ./src/$2.js echo "descrie ('$ 2', function () \ nit );“ > ./spec/$2Spec.js sed -i "" "11a \\ \\  "SpecRunner.html echo" Creat: "echo" \ t- src / $ 2.js "echo" \ t- spec / $ 2Spec.js "echo" Editat: "echo" \ t- SpecRunner.html "else echo" adăugați un nume pentru fișierul "fi ;;" executați ") dacă [" 'care se deschide "" = "/ usr / bin / open"], apoi deschideți ./SpecRunner.html altceva echo "Vă rugăm să deschideți SpecRunner.html în browser "fi ;; *) ajuta;; esac alt ajutor; fi

Continuați, încercați!

 mkdir project cd proiect jazz init jazz creare Dog # ediție src / Dog.js și spec / DogSpec.js jazz run

Apropo, dacă vrei să te distrezi mai mult cu acest proiect, îl poți găsi pe Github.


Concluzie

Deci, tu o ai! Tocmai am scris un scenariu shell shell intermediar; nu era atât de rău, acum, nu-i așa? Nu uita să rămâi acordat pentru următorul curs Tuts + Premium; veți învăța mai multe despre multe dintre tehnicile utilizate în acest articol, precum și nenumărate alte. Distrează-te pe terminal!

Cod