C shell - C shell

C coajă
Tcsh ejecutándose în escritorio Mac OSX.png
tcsh și sh unul lângă altul pe un desktop Mac OS X
Autori originali Bill Joy
Eliberarea inițială 1978 ; Acum 43 de ani ( 1978 )
Versiune stabila
6.20.00 / 24 noiembrie 2016 ; acum 4 ani ( 24.11.2016 )
Repertoriu Editați acest lucru la Wikidata
Scris in C
Sistem de operare BSD , UNIX , Linux , macOS
Tip Unix shell
Licență Licență BSD
C Shell rulează pe Windows Services pentru UNIX

C shell ( csh sau versiunea îmbunătățită, tcsh ) este un Unix shell creat de Bill Joy în timp ce el a fost un student absolvent de la Universitatea din California, Berkeley la sfârșitul anilor 1970. Acesta a fost distribuit pe scară largă, începând cu lansarea 2BSD a Berkeley Software Distribution (BSD) pe care Joy a distribuit-o pentru prima dată în 1978. Alți contribuabili timpurii la idei sau cod au fost Michael Ubell, Eric Allman , Mike O'Brien și Jim Kulp.

Învelișul C este un procesor de comandă care se execută de obicei într-o fereastră de text, permițând utilizatorului să tasteze și să execute comenzi. Shell-ul C poate citi și comenzi dintr-un fișier, numit script . La fel ca toate shell-urile Unix, acesta acceptă metacaractere , piping-uri , aici documente , substituirea comenzilor , variabile și structuri de control pentru testarea condițiilor și iterație . Ceea ce a diferențiat shell-ul C de altele, mai ales în anii 1980, au fost caracteristicile sale interactive și stilul general. Noile sale caracteristici îl fac mai ușor și mai rapid de utilizat. Stilul general al limbii arăta mai degrabă ca C și a fost văzut ca fiind mai ușor de citit.

Pe multe sisteme, cum ar fi macOS și Red Hat Linux , csh este de fapt tcsh , o versiune îmbunătățită a csh. Adesea , unul dintre cele două fișiere este fie un link hard sau un link simbolic la altul, astfel încât să fie numele se referă la aceeași versiune îmbunătățită a shell -ului C.

Pe Debian și unele derivate (inclusiv Ubuntu ), există două pachete diferite: csh și tcsh. Prima se bazează pe versiunea BSD originală a csh, iar cea din urmă este tcsh îmbunătățită.

tcsh a adăugat nume de fișier și finalizarea comenzilor și concepte de editare a liniei de comandă împrumutate din sistemul Tenex , care este sursa „t” -ului . Deoarece a adăugat doar funcționalitate și nu a modificat ceea ce era acolo, tcsh a rămas compatibil înapoi cu shell-ul C original. Deși a început ca o ramură laterală din arborele sursă original creat de Joy, tcsh este acum ramura principală pentru dezvoltarea continuă. tcsh este foarte stabil, dar noile versiuni continuă să apară aproximativ o dată pe an, constând în principal din remedieri minore ale erorilor.

Obiectivele și caracteristicile de proiectare

Principalele obiective de proiectare pentru shell-ul C au fost că acesta ar trebui să semene mai mult cu limbajul de programare C și că ar trebui să fie mai bun pentru utilizarea interactivă.

Mai mult ca C

Sistemul Unix fusese scris aproape exclusiv în C, așa că primul obiectiv al shell-ului C era un limbaj de comandă care era mai stilistic coerent cu restul sistemului. Cuvintele cheie, utilizarea parantezelor și gramatica de expresie încorporată a shell-ului C și suportul pentru tablouri au fost puternic influențate de C.

Conform standardelor de astăzi, shell-ul C poate să nu pară mai asemănător cu C decât multe alte limbaje de scriptare populare. Dar, prin anii '80 și '90, diferența a fost văzută ca izbitoare, în special în comparație cu shell-ul Bourne (cunoscut și sub numele de sh ), shell-ul dominant atunci scris de Stephen Bourne la Bell Labs . Acest exemplu ilustrează mai convenționale C shellului operatorilor de expresie și sintaxă .

Bourne shell

#!/bin/sh
if [ $days -gt 365 ]
then
   echo This is over a year.
fi

C coajă

#!/bin/csh
if ( $days > 365 ) then
   echo This is over a year.
endif

Lui Bourne îi lipsea o gramatică de expresie . Condiția dintre paranteze pătrate trebuia evaluată prin mijloacele mai lente de a rula programul de testare externă . ifComanda lui sh a luat cuvintele sale de argument ca o nouă comandă care trebuie rulată ca proces copil . Dacă copilul a ieșit cu un cod de returnare zero , sh ar căuta o clauză then (o afirmație separată, dar adesea scrisă unită pe aceeași linie cu un punct și virgulă) și ar rula acel bloc imbricat. În caz contrar, ar rula celălalt. Legarea dură a programului de testare atât ca „ test” , cât și „ [„ a oferit avantajul notațional al parantezelor pătrate și aspectul că funcționalitatea testului face parte din limbajul sh. Folosirea unui cuvânt cheie inversat pentru a marca sfârșitul unui bloc de control a fost un stil împrumutat de la ALGOL 68 .

În schimb, csh putea evalua expresia direct, ceea ce o făcea mai rapidă. De asemenea, a pretins o mai bună lizibilitate: expresiile sale foloseau o gramatică și un set de operatori copiați în cea mai mare parte din C, niciunul dintre cuvintele sale cheie nu a fost inversat, iar stilul general seamănă mai mult cu C.

Iată un al doilea exemplu, comparând scripturile care calculează primele 10 puteri ale lui 2.

Bourne shell

#!/bin/sh
i=2
j=1
while [ $j -le 10 ]
do
   echo '2 **' $j = $i
   i=`expr $i '*' 2`
   j=`expr $j + 1`
done

C coajă

#!/bin/csh
set i = 2
set j = 1
while ( $j <= 10 )
   echo '2 **' $j = $i
   @ i *= 2
   @ j++
end

Din nou din cauza lipsei unei expresii gramaticale, scriptul sh folosește înlocuirea comenzii și comanda expr . (Modern POSIX coajă nu au o astfel de gramatica: declarația poate fi scrisă i=$((i * 2))sau : $((i *= 2)).)

În cele din urmă, iată un al treilea exemplu, care arată stilurile diferite pentru o instrucțiune switch .

Bourne shell

#!/bin/sh
for i in d*
do
   case $i in
      d?) echo $i is short ;;
      *) echo $i is long ;;
   esac
done

C coajă

#!/bin/csh
foreach i ( d* )
   switch ( $i )
      case d?:
         echo $i is short
         breaksw
      default:
         echo $i is long
   endsw
end

În scriptul sh, „ ;;” marchează sfârșitul fiecărui caz deoarece sh interzice declarații nule altfel.

Îmbunătățiri pentru utilizare interactivă

Al doilea obiectiv a fost ca shell-ul C să fie mai bun pentru utilizare interactivă. A introdus numeroase caracteristici noi care au făcut-o mai ușoară, mai rapidă și mai ușor de utilizat prin tastarea comenzilor la un terminal. Utilizatorii ar putea face lucrurile cu mult mai puține apăsări de tastă și au rulat mai rapid. Cele mai semnificative dintre aceste noi caracteristici au fost istoricul și mecanismele de editare, pseudonimele, stivele de directoare, notația tilde, cdpath, controlul locului de muncă și hashing-ul căii. Aceste noi caracteristici s-au dovedit foarte populare, iar multe dintre ele au fost copiate de alte shell-uri Unix.

Istorie

Istoricul permite utilizatorilor să-și amintească comenzile anterioare și să le execute din nou tastând doar câteva apăsări rapide de tastă. De exemplu, tastarea a două semne de exclamare (" !!") ca comandă determină executarea comenzii imediat precedente. Alte combinații scurte de apăsare de tastă, de exemplu, „ !$” (adică „argumentul final al comenzii anterioare”), permit ca biții și bucățile de comenzi anterioare să fie lipite împreună și editate pentru a forma o nouă comandă.

Editarea operatorilor

Editarea se poate face nu numai pe textul unei comenzi anterioare, ci și pe înlocuiri variabile. Operatorii variază de la căutarea / înlocuirea șirurilor simple până la analizarea unui nume de cale pentru a extrage un anumit segment.

Aliasuri

Aliasurile permit utilizatorului să introducă numele unui alias și să aibă shell-ul C care îl extinde intern în orice set de cuvinte definite de utilizator. Pentru multe situații simple, aliasurile rulează mai repede și sunt mai convenabile decât scripturile.

Stivă de directoare

Directorul de stivă permite utilizatorului să împingă sau pop directorul curent de lucru , ceea ce face mai ușor pentru a sări înainte și înapoi între diferite locuri din sistemul de fișiere.

Notare tilde

Notarea Tilde oferă o modalitate de prescurtare a specificării numelor de cale în legătură cu directorul de acasă utilizând caracterul " ~".

Completarea numelui fișierului

Cheia de evacuare poate fi folosit interactiv pentru a arăta posibile completări un nume de fișier de la sfârșitul liniei de comandă curente.

Cdpath

Cdpath extinde noțiunea unei căi de căutare la comanda cd(schimbare director): Dacă directorul specificat nu se află în directorul curent , csh va încerca să îl găsească în directorele cdpath.

Controlul postului

Până în anii 1980, majoritatea utilizatorilor aveau doar terminale simple de tip caracter care împiedicau mai multe ferestre, deci nu puteau lucra decât la o singură sarcină la un moment dat. Controlul de job al shell-ului C a permis utilizatorului să suspende activitatea curentă și să creeze o nouă instanță a shell-ului C, numită job, prin tastare ^Z. Utilizatorul ar putea apoi comuta înainte și înapoi între lucrări folosind fgcomanda. S-a spus că locul de muncă activ se află în prim-plan. Se spunea că alte locuri de muncă sunt fie suspendate (oprite), fie rulate în fundal .

Hashing de cale

Hash-ul de cale accelerează căutarea fișierelor executabile de către shell-ul C. În loc să efectueze un apel de sistem de fișiere în fiecare director de cale, unul câte unul, până când acesta găsește fișierul sau rămâne fără posibilități, shell-ul C consultă un tabel de hash intern construit prin scanarea directorilor de căi. Acel tabel poate spune de obicei shell-ului C unde să găsească fișierul (dacă există) fără a fi nevoie să caute și poate fi reîmprospătat cu rehashcomanda.

Prezentare generală a limbii

Învelișul C funcționează pe rând. Fiecare linie este simbolizată într-un set de cuvinte separate prin spații sau alte caractere cu semnificație specială, incluzând paranteze, conductoare și operatori de redirecționare de intrare / ieșire, punct și virgulă și ampersands.

Afirmații de bază

O declarație de bază este una care execută pur și simplu o comandă. Primul cuvânt este luat ca nume al comenzii de executat și poate fi fie o comandă internă, de exemplu echo, fie o comandă externă. Restul cuvintelor sunt transmise ca argumente la comandă.

La nivelul enunțurilor de bază, iată câteva dintre caracteristicile gramaticii:

Comodele

Shell-ul C, la fel ca toate shell-urile Unix, tratează orice argument din linia de comandă care conține caractere wildcard ca un model și îl înlocuiește cu lista tuturor numelor de fișiere care se potrivesc (vezi globbing ).

  • * se potrivește cu orice număr de caractere.
  • ? se potrivește cu orice personaj.
  • [... se ]potrivește cu oricare dintre caracterele din paranteze. Intervalele sunt permise, folosind cratima.
  • [^... se ]potrivește cu orice caracter care nu este în set

Shell-ul C a introdus, de asemenea, mai multe facilități de notare (uneori cunoscute sub numele de globbling extins ), deoarece au fost copiate de alte shell-uri Unix.

  • abc{def,ghi}este alternanță (cunoscută și sub numele de expansiune bretele ) și se extinde la abcdef abcghi .
  • ~ înseamnă directorul de acasă al utilizatorului curent.
  • ~userînseamnă utilizator“ e directorul acasă.

*/*.cSunt acceptate mai multe metacaractere la nivel de director, de exemplu, " ".

Începând cu versiunea 6.17.01, comodinul recursiv la zsh (de ex. „ **/*.c” Sau „ ***/*.html”) este de asemenea acceptat cu globstaropțiunea.

Acordarea responsabilității pentru interpretarea comodinelor a fost o decizie importantă pentru Unix. Însemna că metacaracterele ar funcționa cu fiecare comandă și întotdeauna în același mod. Cu toate acestea, decizia s-a bazat pe capacitatea Unix de a trece în mod eficient liste de argumente lungi prin apelul de sistem exec pe care csh îl folosește pentru a executa comenzi. Spre deosebire, pe Windows , interpretarea cu comodine este realizată în mod convențional de fiecare aplicație. Aceasta este o moștenire a MS-DOS, care a permis doar trecerea unei linii de comandă de 128 de octeți către o aplicație, ceea ce face ca caracterele wildcard prin promptul de comandă DOS să fie impracticabile. Deși Windows-ul modern poate transmite linii de comandă de până la aproximativ 32K caractere Unicode , sarcina pentru interpretarea comodin rămâne cu aplicația.

Redirecționare I / O

În mod implicit, când csh execută o comandă, comanda moștenește fișierele stdio ale csh pentru stdin , stdout și stderr , care în mod normal toate indică fereastra consolei unde rulează shell-ul C. Operatorii de redirecționare i / o permit comenzii să utilizeze un fișier în loc de intrare sau ieșire.

  • > fișier înseamnă că stdout va fi scris în fișier , suprascriindu-l dacă există și creându-l dacă nu. În continuare apar erori la fereastra shell.
  • >& fișier înseamnă că atât stdout cât și stderr vor fi scrise în fișier , suprascriindu-l dacă există și creându-l dacă nu.
  • >> fișier înseamnă că stdout va fi adăugat la sfârșitul fișierului .
  • >>& fișier înseamnă că atât stdout cât și stderr vor fi adăugate la sfârșitul fișierului .
  • < fișier înseamnă că stdin va fi citit din fișier .
  • << șirul este un document aici . Stdin va citi următoarele rânduri până la cel care se potrivește șirului .

Alăturarea

Comenzile pot fi unite pe aceeași linie.

  • ; înseamnă să executați prima comandă și apoi următoarea.
  • &&înseamnă rulați prima comandă și, dacă reușește cu un cod de returnare 0 , rulați următoarea.
  • || înseamnă rulați prima comandă și, dacă eșuează cu un cod de returnare diferit de zero, rulați următoarea.

Conducte

Comenzile pot fi conectate folosind o conductă, ceea ce face ca ieșirea unei comenzi să fie introdusă în intrarea următoarei. Ambele comenzi rulează simultan .

  • |înseamnă conectare stdout la stdin a comenzii următoare. În continuare apar erori la fereastra shell.
  • |& înseamnă conectați atât stdout cât și stderr la stdin din următoarea comandă.

Rularea simultană înseamnă „în paralel”. Într-un sistem cu mai multe nuclee (procesor multiplu), comenzile canalizate pot fi literalmente executate în același timp, altfel programatorul din sistemul de operare se repartizează între ele.

Având o comandă, de exemplu, " a | b", shell-ul creează o conductă , apoi pornește ambele ași bcu stdio pentru cele două comenzi redirecționate astfel încât să ascrie stdout-ul său în intrarea conductei în timp ce bcitește stdin din ieșirea conductei. Țevile sunt implementate de sistemul de operare cu o anumită cantitate de tamponare, astfel încât să apoată scrie o vreme înainte ca țeava să se umple, dar odată ce țeava se umple, orice scriere nouă se va bloca în sistemul de operare până când bcitește suficient pentru a debloca noi scrieri. Dacă bîncearcă să citească mai multe date decât sunt disponibile, se va bloca până când ava scrie mai multe date sau până când conducta se închide, de exemplu, dacă aiese.

Înlocuirea variabilă

Dacă un cuvânt conține un semn de dolar, " $", următoarele caractere sunt luate ca numele unei variabile și referința este înlocuită cu valoarea acelei variabile. Diferiti operatori de editare, tastati ca sufixe la referinta, permit editarea calea (de exemplu, " :e" pentru a extrage doar extensia) si alte operatiuni.

Citând și evadând

Mecanismele de citare permit altfel caracterelor speciale, cum ar fi spațiile albe, metacaracterele, parantezele și semnele de dolar, să fie luate ca text literal .

  • \ înseamnă a lua următorul caracter ca un caracter literal obișnuit.
  • "șirul" este un citat slab. Spațiul alb închis și metacaracterele sunt luate ca litere, dar se efectuează în continuare substituiri de variabile și comenzi.
  • 'șirul' este un citat puternic. Întregul șir închis este luat ca literal.

Înlocuirea comenzii

Înlocuirea comenzii permite ca ieșirea unei comenzi să fie folosită ca argumente pentru o altă.

  • `comanda` înseamnă preluarea comenzii , analizați-o în cuvinte și lipiți-o înapoi în linia de comandă.

Executarea fundalului

În mod normal, atunci când shell-ul C pornește o comandă, așteaptă finalizarea comenzii înainte de a oferi utilizatorului o altă solicitare de semnalizare că o nouă comandă poate fi tastată.

  • comanda & înseamnă pornirea comenzii în fundal și solicitarea imediat pentru o nouă comandă.

Sub-coajă

Un subshell este o copie secundară separată a shell-ului care moștenește starea curentă, dar care poate face apoi modificări, de exemplu, în directorul curent, fără a afecta părintele.

  • ( comenzi ) înseamnă executarea comenzilor într-un sub-shell.

Structuri de control

Învelișul C oferă structuri de control atât pentru testarea stării, cât și pentru iterație . Structurile de control pentru testarea condițiilor sunt instrucțiunile if și switch. Structurile de control ale iterației sunt declarațiile while, foreach și repeat.

afirmatie if

Există două forme ale afirmației if . Forma scurtă este tastată pe o singură linie, dar poate specifica o singură comandă dacă expresia este adevărată.

if ( expression ) command

Forma lungă folosește cuvinte cheie then, else și endif pentru a permite blocuri de comenzi să fie imbricate în interiorul condiției.

if ( expression1 ) then
    commands
else if ( expression2 ) then
    commands
    ...
else
    commands
endif

În cazul în care cuvintele cheie else și dacă apar pe aceeași linie, lanțuri csh, mai degrabă decât cuiburi blocul este terminat cu un singur endif.

declarație de comutare

Instrucțiunea switch compară un șir cu o listă de modele, care pot conține caractere wildcard. Dacă nimic nu se potrivește, acțiunea implicită, dacă există una, este luată.

switch ( string )
    case pattern1:
        commands
        breaksw
    case pattern2:
        commands
        breaksw
        ...
    default:
        commands
        breaksw
endsw

în timp ce afirmație

While evalueaza o expresie. Dacă este adevărat, shell-ul execută comenzile imbricate și apoi se repetă atât timp cât expresia rămâne adevărată.

while ( expression )
    commands
end

pentru fiecare declarație

Instrucțiunea foreach ia o listă de valori, de obicei o listă de nume de fișiere produse prin metacaracter și apoi pentru fiecare, setează variabila buclă la acea valoare și rulează comenzile imbricate.

foreach loop-variable ( list-of-values )
    commands
end

declarație repetată

Instrucțiunea repeat repetă o singură comandă de mai multe ori.

repeat integer command

Variabile

Shell-ul C implementează atât variabile de shell, cât și de mediu . Variabilele de mediu, create folosind setenvinstrucțiunea, sunt întotdeauna șiruri simple, transmise oricăror procese copil , care recuperează aceste variabile prin envp[]argumentul către main().

Variabilele Shell, create folosind instrucțiunile setsau @, sunt interne C shell. Ele nu sunt transmise proceselor copilului. Variabilele Shell pot fi fie șiruri simple, fie matrice de șiruri. Unele dintre variabilele de shell sunt predefinite și utilizate pentru a controla diferite opțiuni de shell C interne, de exemplu, ce ar trebui să se întâmple dacă un wildcard nu se potrivește cu nimic.

În versiunile actuale ale csh, șirurile pot avea o lungime arbitrară, până la milioane de caractere.

Expresii

Shell-ul C implementează o gramatică de expresie de 32 de biți întregi cu operatori împrumutați de la C, dar cu câțiva operatori suplimentari pentru comparații de șiruri și teste ale sistemului de fișiere, de ex. Operatorii trebuie să fie separați prin spații albe de operanzi. Variabilele sunt menționate ca $nume .

Precedența operatorului este, de asemenea, împrumutată de la C, dar cu reguli diferite de asociativitate a operatorilor pentru a rezolva ambiguitatea a ceea ce vine primul într-o secvență de operatori de prioritate egală. În C, asociativitatea este de la stânga la dreapta pentru majoritatea operatorilor; în shell C, este de la dreapta la stânga. De exemplu,

// C groups from the left
int i = 10 / 5 * 2;
printf( "%d\n", i ); // prints 4
i = 7 - 4 + 2;
printf( "%d\n", i ); // prints 5
i = 2 >> 1 << 4;
printf( "%d\n", i ); // prints 16
# C shell groups from the right
@ i = 10 / 5 * 2
echo $i # prints 1
@ i = 7 - 4 + 2
echo $i # prints 1
@ i = ( 2 >> 1 << 4 )
echo $i # prints 0

Parantezele din exemplul de shell C sunt pentru a evita confuzia operatorilor de schimbare de biți ca operatori de redirecționare I / O. În oricare dintre limbi, parantezele pot fi întotdeauna utilizate pentru a specifica în mod explicit ordinea de evaluare dorită, chiar dacă este doar pentru claritate.

Recepţie

Deși Stephen Bourne însuși a recunoscut că csh a fost superior shell-ului său pentru utilizare interactivă, nu a fost niciodată la fel de popular pentru scenarii. Inițial și până în anii 1980, csh nu putea fi garantat că va fi prezent pe toate sistemele Unix, dar sh ar putea, ceea ce a făcut-o o alegere mai bună pentru orice scripturi care ar putea fi necesare să ruleze pe alte mașini. Până la jumătatea anilor 1990, csh era disponibil pe scară largă, dar utilizarea csh pentru scripturi s-a confruntat cu noi critici din partea comitetului POSIX , care a specificat că ar trebui să existe un singur shell preferat, KornShell , atât pentru scopuri interactive, cât și pentru scripturi. Shell-ul C s-a confruntat, de asemenea, cu critici din partea altor persoane cu privire la presupusele defecte de sintaxă ale Shell-ului C, caracteristicile lipsă și implementarea slabă.

  • Defecte de sintaxă: au fost în general inconsecvențe simple, dar inutile în definiția limbajului. De exemplu, set, setenvși aliastoate comenzile au făcut practic același lucru, și anume, să asociați un nume cu un șir sau un set de cuvinte. Dar toți trei au avut diferențe ușoare, dar inutile. Un semn egal era necesar pentru un setdar nu pentru setenvsau alias; paranteze au fost necesare în jurul unei liste de cuvinte pentru o , setdar nu și pentru setenvsau alias, etc. În mod similar, if, switchși constructe looping folosesc inutil diferite cuvinte cheie ( endif, endswși end) pentru a pune capăt blocurilor imbricate.
  • Funcții care lipsesc: cele mai frecvent citate sunt lipsa abilității de a manipula independent fișierele stdio și suportul pentru funcții. În timp ce funcțiile shell Bourne nu aveau decât variabile locale, pseudonimele lui Csh - cel mai apropiat analog în Csh de funcții - erau limitate la linii unice de cod, chiar dacă majoritatea construcțiilor de control al fluxului necesitau recunoașterea liniilor noi. Ca urmare, scripturile Csh nu au putut fi defalcate funcțional, așa cum ar putea fi programele C în sine, iar proiectele mai mari au avut tendința de a trece fie la scriptul shell Bourne, fie la codul C.
  • Implementarea: care a folosit un analizor ad hoc , a atras cele mai serioase critici. La începutul anilor 1970, tehnologia de compilare era suficient de matură încât majoritatea implementărilor de limbaj noi foloseau fie un analizor de sus în jos, fie de jos în sus capabil să recunoască o gramatică complet recursivă . Nu se știe de ce a fost ales în schimb un design ad hoc pentru shell-ul C. Poate fi pur și simplu că, așa cum a spus Joy într-un interviu în 2009, „Când am început să fac aceste lucruri cu Unix, nu eram un programator foarte bun”. Proiectarea ad hoc a însemnat că limbajul shell C nu a fost complet recursiv. A existat o limită a complexității unei comenzi pe care o putea gestiona.

A funcționat pentru majoritatea comenzilor tastate interactiv, dar pentru comenzile mai complexe pe care un utilizator le-ar putea scrie într-un script, ar putea eșua cu ușurință, producând doar un mesaj de eroare criptic sau un rezultat nedorit. De exemplu, shell-ul C nu poate suporta conducte între structurile de control. Încercarea de a canaliza ieșirea unei foreachcomenzi greppur și simplu nu a funcționat. (Rezolvarea, care funcționează pentru multe dintre reclamațiile legate de analizor, este de a diviza codul în scripturi separate. Dacă foreacheste mutat într-un script separat, canalizarea funcționează deoarece scripturile sunt rulate prin falsificarea unei noi copii a csh care moștenește mânerele stdio corecte.)

Un alt exemplu este comportamentul nedorit din următoarele fragmente. Ambele par să însemne „Dacă„ fișierul meu ”nu există, creați-l scriind„ textul meu ”în el”. Dar versiunea din dreapta creează întotdeauna un fișier gol, deoarece ordinea de evaluare a shell-ului C este să caute și să evalueze operatorii de redirecționare I / O pe fiecare linie de comandă pe măsură ce o citește, înainte de a examina restul liniei pentru a vedea dacă conține o structură de control.

# Works as expected
if ( ! -e myfile ) then
   echo mytext > myfile
endif
# Always creates an empty file
if (! -e myfile) echo mytext > myfile
# Workaround
if (! -e myfile) eval "echo mytext > myfile"

Implementarea este, de asemenea, criticată pentru mesajele sale de eroare notoriu slabe, de exemplu, „0 eveniment nu a fost găsit”, care nu oferă informații utile despre problemă.

Influență

Shell Hamilton C pe 64 de biți pe un desktop Windows 7 .

Shell-ul C a fost extrem de reușit în introducerea unui număr mare de inovații, inclusiv mecanismul istoric , pseudonimele , notația tilde , completarea interactivă a numelui de fișier, o gramatică de expresie încorporată în shell și multe altele, care au fost copiate de alte shell-uri Unix. Dar, spre deosebire de sh , care a generat un număr mare de clone dezvoltate independent, inclusiv ksh și bash , sunt cunoscute doar două clone csh . (Deoarece tcsh se bazează pe codul csh scris inițial de Bill Joy, nu este considerat o clonă.)

În 1986, Allen Holub a scris On Command: Writing a Unix-Like Shell pentru MS-DOS , o carte care descrie un program pe care l-a scris numit „SH”, dar care de fapt a copiat designul limbajului și caracteristicile csh, nu sh. Dischetele însoțitoare care conțin sursă completă pentru SH și pentru un set de bază de utilități de tip Unix (cat, cp, grep etc.) au fost disponibile de la editor la 25 USD și respectiv 30 USD. Structurile de control, gramatica expresiei, mecanismul istoric și alte caracteristici din SH-ul lui Holub au fost identice cu cele ale shell-ului C.

În 1988, Laboratoarele Hamilton au început să livreze Hamilton C shell pentru OS / 2 . Acesta a inclus atât o clonă csh, cât și un set de utilități de tip Unix. În 1992, Hamilton C a fost lansat pentru Windows NT . Versiunea Windows continuă să fie susținută în mod activ, dar versiunea OS / 2 a fost întreruptă în 2003. O referință rapidă la începutul anului 1990 a descris intenția ca „respectarea deplină a întregului limbaj shell C (cu excepția controlului jobului )”, dar cu îmbunătățiri ale designului limbii și adaptarea la diferențele dintre Unix și un PC. Cea mai importantă îmbunătățire a fost un analizor de sus în jos care permite structurilor de control să fie cuibărite sau canalizate, ceva ce shell-ul C original nu putea suporta, având în vedere analizatorul său ad hoc. Hamilton a adăugat, de asemenea, noi caracteristici de limbaj, inclusiv proceduri încorporate și definite de utilizator, variabile locale structurate în blocuri și aritmetică în virgulă mobilă. Adaptarea la un PC a inclus suport pentru numele de fișier și alte convenții de pe un PC și utilizarea firelor în loc de furci (care nu erau disponibile nici sub OS / 2, nici pe Windows) pentru a realiza paralelism , de exemplu, în configurarea unei conducte.

Vezi si

Referințe

Lecturi suplimentare

linkuri externe