Scrivere script di shell può essere piuttosto scoraggiante, soprattutto perché la shell non è la più amichevole delle lingue da usare. Tuttavia, spero di mostrarti in questo tutorial che lo scripting di shell non è così difficile o spaventoso come potresti aspettarti.
Per questo tutorial, scriveremo uno script che rende il processo di utilizzo del framework di test Jasmine un po 'più semplice. In realtà, non userei questo script oggi; Vorrei usare Grunt.js o qualcosa di simile. Comunque, ho scritto questo script prima che Grunt fosse in giro, e ho scoperto che scrivere era un ottimo modo per stare più a tuo agio con lo scripting di shell, ecco perché lo stiamo usando.
Una nota: questo tutorial è liberamente associato al mio prossimo corso Tuts + Premium, "Advanced Command Line Techniques". Per saperne di più su praticamente qualsiasi cosa in questo tutorial, rimanete sintonizzati per il rilascio di quel corso. Di seguito in questo tutorial, verrà indicato come "il corso".
Quindi, il nostro script, che io chiamo jazz
, avrà quattro caratteristiche principali:
Iniziamo con il file di script.
Scrivere uno script di shell è utile solo se puoi usarlo dal terminale; per poter usare i tuoi script personalizzati sul terminale, devi metterli in una cartella che si trova nel tuo terminale SENTIERO
variabile (puoi vedere il tuo SENTIERO
variabile eseguendo echo $ PATH
). Ho creato un ~ / Bin
cartella (dove ~
è la home directory) sul mio computer, ed è lì che mi piace mantenere script personalizzati (se fai lo stesso, dovrai aggiungerlo al tuo percorso). Quindi, basta creare un file, chiamato jazz
, e mettilo nella tua cartella.
Ovviamente, dovremo rendere eseguibile quel file; altrimenti, non saremo in grado di eseguirlo. Possiamo farlo eseguendo il seguente comando:
chmod + x jazz
Ora che possiamo effettivamente eseguire lo script, aggiungiamo una parte molto importante. Tutti gli script di shell dovrebbero iniziare con uno shebang). Come dice Wikipedia, questa dovrebbe essere la prima riga della sceneggiatura; indica quale interprete o shell, con cui questo script deve essere eseguito. Utilizzeremo semplicemente una shell standard di base:
#! / Bin / sh
Va bene, con tutto ciò che è stato configurato, siamo pronti per iniziare a scrivere il codice vero e proprio.
In precedenza, ho sottolineato quali dovrebbero essere le diverse caratteristiche del nostro script di shell. Ma come farà lo script a sapere quale funzione eseguire? Useremo una combinazione di un parametro shell e un'istruzione case. Quando eseguiremo lo script dalla riga di comando, useremo un sottocomando, come questo:
jazz init jazz creare SomeFile jazz eseguire aiuto jazz
Questo dovrebbe sembrare familiare, specialmente se hai usato Git:
git init git status git commit
Basato su quel primo parametro (dentro
, creare
, correre
, Aiuto
), la nostra dichiarazione del caso deciderà cosa eseguire. Tuttavia, abbiamo bisogno di un caso predefinito: cosa succede se non viene fornito un primo parametro o viene visualizzato un primo parametro non riconosciuto? In questi casi, mostreremo il testo della guida. Quindi iniziamo!
Iniziamo con il Se
affermazione che controlla il nostro primo parametro:
se [$ 1] poi # fai altro # mostra help fi
All'inizio potresti essere un po 'confuso, perché una shell Se
la dichiarazione è piuttosto diversa da un linguaggio di programmazione "normale" Se
dichiarazione. Per avere una migliore comprensione di esso, guarda lo screencast sulle dichiarazioni condizionali nel corso. Questo codice controlla la presenza di un primo parametro ($ 1
); se è lì, eseguiremo il poi
codice; altro
, mostreremo il testo della guida.
È una buona idea avvolgere la stampa del testo di aiuto in una funzione, perché dobbiamo chiamarla più di una volta. Abbiamo bisogno di definire la funzione prima che venga chiamata, quindi la metteremo in cima. Mi piace, perché ora, non appena apro il file, vedo la documentazione per lo script, che può essere un utile promemoria quando si torna al codice che non si vede da un po '. Senza ulteriori indugi, ecco il Aiuto
funzione:
function help () echo "jazz - Un semplice script che rende l'uso del framework di test Jasmine in un progetto standalone un po 'più semplice." echo "echo" jazz init - include jasmine nel progetto "; echo" jazz create FunctionName - crea ./src/FunctionName.js ./spec/FunctionNameSpec.js "; echo" jazz run - esegue test nel browser ";
Ora, sostituiscilo # mostra aiuto
funzione con una chiamata al Aiuto
funzione.
altro aiuto fi
Se c'è un primo parametro, dobbiamo capire quale sia. Per questo, usiamo a Astuccio
dichiarazione:
caso "$ 1" in init) ;; creare) ;; correre) ;; *) Aiuto ;; esac
Passiamo il primo parametro al Astuccio
economico; quindi, dovrebbe corrispondere a una delle quattro cose: "init", "create", "run", o il nostro jolly, caso predefinito. Si noti che non abbiamo un caso esplicito di "aiuto": questo è solo il nostro caso predefinito. Funziona, perché qualsiasi cosa diversa da "init", "create" e "run" non sono comandi che riconosciamo, quindi dovrebbe ottenere il testo di aiuto.
Ora siamo pronti per scrivere il codice funzionale e inizieremo con jazz init
.
jazz init
Tutto il codice che scriviamo qui andrà nei nostri dentro)
caso, dalla dichiarazione del caso di cui sopra. Il primo passo è quello di scaricare la versione standalone di Jasmine, che arriva in un file zip:
echo "Downloading Jasmine ..." arricciatura -sO $ JASMINE_LINK
Per prima cosa facciamo eco a un piccolo messaggio e quindi usiamo arricciare
per scaricare lo zip. Il S
flag lo rende silenzioso (nessun output) e il O
flag salva il contenuto dello zip in un file (altrimenti lo reindirizzerebbe allo standard). Ma che cosa è con quello $ JASMINE_LINK
variabile? Bene, puoi inserire il link effettivo al file zip lì, ma preferisco inserirlo in una variabile per due motivi: in primo luogo, ci impedisce di ripetere parte del percorso, come vedrai tra un minuto. Secondo, con quella variabile nella parte superiore del file, rende facile cambiare la versione di Jasmine che stiamo usando: basta cambiare quella variabile. Ecco la dichiarazione delle variabili (l'ho messa al di fuori di Se
affermazione, vicino alla cima):
JASMIME_LINK = "http://cloud.github.com/downloads/pivotal/jasmine/jasmine-standalone-1.3.1.zip"
Ricorda, non ci sono spazi attorno agli uguali: accedi a quella linea.
Ora che abbiamo il nostro file zip, possiamo decomprimerlo e preparare il contenuto:
decomprimere -qbasename $ JASMINE_LINK
rm -rfbasename $ JASMINE_LINK
src / *. js spec / *. js
In due di queste linee, stiamo usando basename $ JASMINE_LINK
; il basename
comando semplicemente riduce un percorso al nome base: così path / to / file.zip
diventa giusto file.zip
. Questo ci permette di usarlo $ JASMINE_LINK
variabile per fare riferimento al nostro file zip locale.
Dopo aver decompresso, cancelleremo quel file zip, così come tutti i file JavaScript nel src
e spec
le directory. Questi sono i file di esempio di Jasmine e non ne abbiamo bisogno.
Successivamente, abbiamo un problema solo per Mac da affrontare. Per impostazione predefinita, quando si scarica qualcosa da Internet su un Mac, quando si tenta di eseguirlo per la prima volta, verrà richiesto di confermare che si desidera eseguirlo. Questo a causa dell'attributo esteso com.apple.quarantine
che Apple inserisce il file. Dobbiamo rimuovere questo attributo.
se quale xattr> / dev / null && ["xattr SpecRunner.html
"=" com.apple.quarantine "] then xattr -d com.apple.quarantine SpecRunner.html fi
Iniziamo controllando la presenza di xattr
comando, perché non esiste su alcuni sistemi Unix (non sono sicuro, ma potrebbe essere un programma solo per Mac). Se hai guardato lo screencast del corso sui condizionali, saprai che possiamo passare qualsiasi comando a Se
; se ha uno stato di uscita di qualsiasi altra cosa 0
, è falso. Se quale
trova il xattr
comando, uscirà con 0
; altrimenti, uscirà con 1
. In ogni caso, quale
mostrerà un po 'di output; possiamo impedire che ciò venga mostrato reindirizzandolo a / Dev / null
(questo è un file speciale che scarta tutti i dati scritti su di esso).
Quella doppia e commerciale è un AND booleano; è lì per la seconda condizione che vogliamo controllare. Cioè, fa il SpecRunner.html
avere questo attributo? Possiamo semplicemente eseguire il xattr
comando sul file e confrontarlo con la stringa che ci aspettiamo. (Non possiamo solo aspettarci che il file abbia l'attributo, perché puoi effettivamente disattivare questa funzione in Mac OS X, e riceverai un errore quando proverai a rimuoverlo se il file non ha l'attributo).
Quindi se xattr
viene trovato e il file ha l'attributo, lo rimuoveremo con il file d
(per eliminare) bandiera. Piuttosto semplice, giusto?
Il passo finale è modificare SpecRunner.html
. Attualmente contiene tag script per i file JavaScript di esempio che abbiamo eliminato; dovremmo anche cancellare quei tag script. Mi è capitato di sapere che questi tag di script coprono le righe da 12 a 18 nei file. Quindi, possiamo usare l'editor di stream sed
per cancellare quelle linee:
sed -i "" '12, 18d 'SpecRunner.html echo "Jasmine inizializzato!"
Il io
la bandiera dice sed
per modificare il file in posizione o per salvare l'output dal comando allo stesso file passato; la stringa vuota dopo la bandiera significa che non vogliamo sed
per eseguire il backup del file per noi; se lo volessi, potresti semplicemente inserire un'estensione di file in quella stringa (come .bak
, ottenere SpecRunner.html.bak
).
Infine, faremo sapere all'utente che Jasmine è stato inizializzato. E questo è tutto per il nostro jazz init
comando.
il jazz crea
Quindi, consentiremo ai nostri utenti di creare file JavaScript e i relativi file spec associati. Questa parte del codice andrà nella sezione "crea" di Astuccio
dichiarazione che abbiamo scritto in precedenza.
se [$ 2] poi # crea file else echo "per favore includi un nome per il file" fi
Quando si usa il jazz crea
, dobbiamo includere un nome per il file come secondo parametro: jazz crea View
, per esempio. Lo useremo per creare src / View.js
e spec / ViewSpec.js
. Quindi, se non c'è un secondo parametro, ricorderemo all'utente di aggiungerne uno.
Se c'è un nome di file, inizieremo creando questi due file (all'interno di poi
parte sopra):
echo "function $ 2 () \ n \ n"> src / $ 2.js echo "descrivi ('$ 2', function () \ n \ n);" > spec / $ 2Spec.js
Certo, puoi mettere tutto ciò che vuoi nel tuo src
file. Sto facendo qualcosa di essenziale qui; così jazz crea View
creerà src / View.js
con questo:
function View ()
Potresti sostituirlo per primo eco
linea con questo:
echo "var $ 2 = (function () \ n \ tvar $ 2Prototype = \ n \ n \ t; \ n \ n \ treturn \ n \ t \ tcreate: function (attrs) \ n \ t \ t \ tvar o = Object.create ($ 2Prototype); \ n \ t \ t \ textend (o, attrs); \ n \ t \ t \ treturn o; \ n \ t \ t \ n \ t; \ n ());" > src / $ 2.js
E poi jazz crea View
risulterà in questo:
var View = (function () var ViewPrototype = ; return create: function (attrs) var o = Object.create (ViewPrototype); extend (o, attrs); return o;; ()) ;
Quindi, davvero, la tua immaginazione è il limite. Ovviamente, vorrai che il file spec sia il codice standard standard di Jasmine, che è quello che ho sopra; ma puoi modificare ciò che vuoi comunque.
Il prossimo passo è aggiungere i tag di script per questi file SpecRunner.html
. All'inizio, questo potrebbe sembrare complicato: come possiamo aggiungere linee al centro di un file a livello di programmazione? Ancora una volta, lo è sed
questo fa il lavoro.
sed -i "" "11a \\ \\ "SpecRunner.html
Iniziamo come prima: la modifica sul posto senza backup. Quindi il nostro comando: alla riga 11, vogliamo aggiungere le due righe seguenti. È importante sfuggire alle due nuove linee, in modo che vengano visualizzate nel testo. Come puoi vedere, questo semplicemente inserisce quei due tag script, esattamente ciò di cui abbiamo bisogno per questo passaggio.
Possiamo finire con qualche risultato:
echo "Creato:" echo "\ t- src / $ 2.js" echo "\ t- spec / $ 2Spec.js" echo "Modificato:" echo "\ t- SpecRunner.html"
E questo è il jazz crea
!
corsa jazz
L'ultimo passaggio consiste nell'eseguire effettivamente i test. Questo significa aprire il SpecRunner.html
file in un browser. C'è un po 'di avvertimento qui. Su Mac OS X, possiamo usare il Aperto
comando per aprire un file nel suo programma predefinito; questo non funzionerà su nessun altro sistema operativo, ma è così che lo faccio qui. Sfortunatamente, non c'è un vero modo multipiattaforma per farlo, che io sappia. Se stai usando questo script sotto Cygwin su Windows, puoi usare cygstart
al posto di Aperto
; altrimenti, prova a cercare su google "[il tuo sistema operativo] script di script per aprire il browser" e guarda cosa ti viene in mente. Sfortunatamente, alcune versioni di Linux (almeno Ubuntu, nella mia esperienza) hanno un Aperto
comando che è per qualcosa di completamente diverso. Tutto questo per dire, il tuo chilometraggio con il seguente può variare.
if ["'which open'" = '/ usr / bin / open'] quindi apri SpecRunner.html else echo "Per favore apri SpecRunner.html nel tuo browser" fi
Ormai sai esattamente cosa fa questo: se ce l'abbiamo Aperto
, apriremo SpecRunner.html
, altrimenti, stamperemo semplicemente un messaggio che dice all'utente di aprire il file nel browser.
In origine, quello Se
condizione sembrava così:
se quale apri> / dev / null
Come abbiamo fatto con xattr
, ha appena verificato l'esistenza di Aperto
; tuttavia, da quando ho scoperto che c'è un altro Aperto
comando su Linux (anche sul mio server Ubuntu, che non può nemmeno aprire un browser!), ho pensato che sarebbe stato meglio confrontare il percorso del Aperto
programma, poiché quello di Linux è a / Bin / aperto
(ancora, almeno sul server Ubuntu).
Tutte queste parole in più Aperto
potrebbe sembrare una scusa per la mia mancanza di una buona soluzione, in realtà indica qualcosa di importante sulla linea di comando. Non confondere la comprensione del terminale con la comprensione della configurazione di un computer. Questo tutorial e il corso associato ti hanno insegnato un po 'di più sulla shell Bash (e sulla shell Z), ma ciò non significa che ogni computer che utilizzerai sarà configurato allo stesso modo; ci sono molti modi per installare nuovi comandi (o diverse versioni di comandi), così come rimuovere comandi. Sviluppatore di caveat.
Bene, questa è l'intera sceneggiatura! Eccolo di nuovo, tutti insieme:
#! / bin / sh function help () echo "jazz - Un semplice script che rende l'uso del framework di test Jasmine in un progetto standalone un po 'più semplice." echo "" echo "jazz init - include jasmine nel progetto"; echo "jazz create FunctionName - crea ./src/FunctionName.js ./spec/FunctionNameSpec.js"; echo "jazz run - esegue test nel browser"; JASMIME_LINK = "http://cloud.github.com/downloads/pivotal/jasmine/jasmine-standalone-1.3.1.zip" se [$ 1], quindi il caso "$ 1" in init) echo "Downloading Jasmine ..." curl - sO $ JASMIME_LINK unzip -q 'basename $ JASMIME_LINK' rm 'basename $ JASMIME_LINK' src / *. js spec / *. js se quale xattr> / dev / null && ["'xattr SpecRunner.html'" = "com.apple .quarantine "] then xattr -d com.apple.quarantine SpecRunner.html fi -i-" "" 12,18d "SpecRunner.html echo" Jasmine inizializzato! " ;; create) if [$ 2] then echo "function $ 2 () \ n \ n"> ./src/$2.js echo "Descrivi ('$ 2', function () \ nit ('runs'); \ n );" > ./spec/$2Spec.js sed -i "" "11a \\ \\ "SpecRunner.html echo" Creato: "echo" \ t- src / $ 2.js "echo" \ t- spec / $ 2Spec.js "echo" Modificato: "echo" \ t- SpecRunner.html "else echo" per favore aggiungi un nome per il file 'fi ;; "run") se ["' che apre '" =' / usr / bin / open '] quindi apri ./SpecRunner.html else echo "Per favore apri SpecRunner.html nel tuo browser "fi ;; *) help; ;; esac else help; fi
Bene, dai, provaci!
progetto mkdir progetto cd jazz init jazz create Dog # edit src / Dog.js e spec / DogSpec.js jazz run
A proposito, se vuoi divertirti un po 'di più con questo progetto, puoi trovarlo su Github.
Così il gioco è fatto! Abbiamo appena scritto uno script di shell di livello intermedio; non era poi così male, vero? Non dimenticare di rimanere sintonizzato per il mio prossimo corso Tuts + Premium; imparerai molto di più su molte delle tecniche utilizzate in questo articolo, così come innumerevoli altri. Buon divertimento sul terminale!