Cursul 1 - Structura Sistemelor de Calcul PDF
Document Details
Uploaded by Deleted User
Tags
Summary
Acest document este o introducere în structura sistemelor de calcul, descriind hardware-ul, sistemul de operare, programele de aplicație și utilizatori ca componente fundamentale ale unui sistem de calcul.
Full Transcript
CURSUL 1 Structura Sistemelor de Calcul Un sistem de calcul este alcătuit din hardware, un sistem de operare, programe de aplicație și utilizatori. ○ Hardware-ul include CPU, memorie și dispozitive de intrare/ieșire (I/O), fiind resursele de bază. ○ S...
CURSUL 1 Structura Sistemelor de Calcul Un sistem de calcul este alcătuit din hardware, un sistem de operare, programe de aplicație și utilizatori. ○ Hardware-ul include CPU, memorie și dispozitive de intrare/ieșire (I/O), fiind resursele de bază. ○ Sistemul de operare (SO) controlează și coordonează utilizarea resurselor hardware între programe și utilizatori. ○ Programele de aplicație definesc modul în care resursele sistemului sunt folosite pentru a rezolva problemele utilizatorilor, incluzând procesoare de text, compilatoare, browsere, baze de date și jocuri. ○ Utilizatorii pot fi oameni, mașini sau alte computere. Din punct de vedere abstract, componentele unui calculator funcționează împreună prin intermediul unuia sau mai multor procesoare și controlere de dispozitive care comunică printr-o magistrală ce permite accesul la memorie. Aceasta duce la execuția concurentă a procesoarelor și dispozitivelor, care concurează pentru ciclurile de acces la memorie. Ce Este un Sistem de Operare? Un sistem de operare (SO) este un program care intermediază între utilizator și hardware-ul calculatorului. Obiectivele unui SO includ: ○ Executarea programelor utilizator și facilitarea rezolvării problemelor. ○ Asigurarea unei utilizări convenabile a sistemului de calcul. ○ Definirea abstractizărilor software, de exemplu, lucrul cu fișiere în loc de blocuri de disc sau cu conexiuni de rețea în loc de șiruri de biți. ○ Utilizarea eficientă a hardware-ului. Rolul unui SO depinde de perspectivă: ○ Utilizatorii doresc ușurință în utilizare și performanță, fără a se preocupa de utilizarea resurselor. ○ Calculatoarele mari trebuie să satisfacă așteptările tuturor utilizatorilor. SO este un alocator de resurse și un program de control care optimizează utilizarea hardware-ului și gestionează execuția programelor. ○ Stațiile de lucru au resurse dedicate, dar adesea folosesc resurse partajate de servere. ○ Dispozitivele mobile au resurse limitate, optimizate pentru ușurința utilizării și durata de viață a bateriei, cu interfețe speciale precum ecrane tactile și recunoaștere vocală. ○ Unele computere, cum ar fi sistemele încorporate, au interfețe limitate sau deloc și rulează în principal fără intervenția utilizatorului. Definiția unui Sistem de Operare Nu există o definiție universal acceptată a unui SO. O definiție aproximativă este „software-ul cu care este echipat calculatorul livrat de producător”. Kernel-ul este programul care rulează în permanență pe calculator și este nucleul sistemului de operare. Restul software-ului include: ○ Programe de sistem (livrate cu SO, dar nu fac parte din kernel). ○ Programe de aplicație (toate programele care nu sunt asociate cu SO). Sistemele de operare de uz general (GPOS) și cele mobile includ middleware, care oferă servicii suplimentare dezvoltatorilor de aplicații, cum ar fi baze de date, multimedia și grafică. Serviciile Sistemului de Operare SO oferă un mediu de execuție pentru programe și servicii pentru programe și utilizatori. Unele servicii SO oferă funcții de asistență pentru utilizator, cum ar fi: ○ Interfața utilizator (UI): Poate fi o interfață de linie de comandă (CLI), o interfață grafică (GUI), un ecran tactil sau procesare batch. ○ Execuția programelor: SO încarcă programe în memorie și le execută, terminându-le normal sau anormal, cu indicarea erorilor. ○ Operații de intrare/ieșire (I/O): Programele pot solicita operații I/O care implică accesul la fișiere sau dispozitive I/O. ○ Manipularea fișierelor: SO gestionează sistemul de fișiere și capacitatea programelor de a citi, scrie, crea, șterge, căuta și afișa informații despre fișiere și directoare, precum și de a gestiona permisiunile de acces. ○ Comunicarea: Procesele pot schimba informații pe același calculator sau între calculatoare conectate în rețea, folosind memorie partajată sau transmitere de mesaje. ○ Detectarea erorilor: SO trebuie să fie constant conștient de posibile erori în CPU, memorie, dispozitive I/O sau programele utilizatorilor. SO ia măsurile adecvate pentru a asigura un calcul corect și consistent. Instrumentele de depanare ajută utilizatorii și programatorii să utilizeze eficient sistemul. Alte servicii SO asigură funcționarea eficientă a sistemului în prezența resurselor partajate: ○ Alocarea resurselor: Când mai mulți utilizatori sau programe rulează concurent, SO alocă resurse precum cicluri CPU, memorie principală, stocare de fișiere și dispozitive I/O. ○ Logarea execuției: Necesară pentru a contabiliza utilizarea resurselor de către utilizatori și tipul de resurse folosite. ○ Protecție și securitate: Informațiile din sistemele multi-utilizator sau conectate în rețea pot avea acces restricționat, iar procesele concurente nu trebuie să interfereze între ele. SO trebuie să protejeze dispozitivele I/O externe de încercări de acces nevalide. ○ Protecția asigură controlul tuturor acceselor la resursele sistemului. ○ Securitatea implică autentificarea utilizatorilor și protejarea sistemului împotriva amenințărilor externe. Instalarea și Bootarea SO Sistemele de operare sunt proiectate să ruleze pe o varietate de sisteme cu diferite periferice. De obicei, SO este deja instalat pe calculator la cumpărare. Este posibil să se compileze și să se instaleze alte SO. ○ Dacă se generează un SO de la zero, pașii includ scrierea codului SO, configurarea pentru calculatorul țintă, compilarea, instalarea și bootarea calculatorului sub noul SO. ○ Un exemplu, Linux, implică descărcarea codului sursă, configurarea kernel-ului, compilarea kernel-ului și a modulelor și instalarea noului kernel în sistem. CURSUL 2 Pornirea Sistemului (Procesul de Boot) ○ La pornirea calculatorului, execuția începe într-un loc fix din memorie. ○ Sistemul de operare (SO) trebuie să fie disponibil pentru hardware pentru a fi pornit. ○ Un mic cod, numit bootstrap loader, BIOS sau UEFI, stocat în ROM sau EEPROM, localizează kernelul, îl încarcă în memorie și îl pornește. ○ Uneori, procesul de boot are doi pași, folosind un bloc de boot din ROM care încarcă bootstrap loader-ul de pe disc. ○ Sistemele moderne folosesc Unified Extensible Firmware Interface (UEFI) în locul BIOS. ○ Un bootstrap loader uzual este GRUB, care permite selectarea kernel-ului de pe discuri multiple, cu versiuni și opțiuni diferite. ○ Boot loader-ele permit diferite stări de boot, cum ar fi single-user mode. Procesul de Boot Unix ○ Primul sector al discului de boot (Master Boot Record - MBR sau succesorul său GPT) conține tabela de partiții de disc și codul de bootstrap (boot loader). ○ Loader-ul identifică partiția de boot și încarcă codul kernel (nucleul sistemului de operare). ○ La acest nivel, nu există noțiunea de fișier, ci doar sectoare de disc, deci există două soluții: Loader-ul cunoaște o hartă hardcoded a sectoarelor de disc ce conțin codul kernel. Această soluție necesită actualizări când imaginea kernelului se schimbă. Loader-ul are acces la drivere care înțeleg structura sistemului de fișiere și pot identifica kernelul ca pe un fișier oarecare. ○ Exemple de boot loaders Linux: Lilo, Grub. ○ Fișierul cu imaginea kernelului (de exemplu, /boot/vmlinuz pentru Linux) se încarcă în memorie, iar kernelul preia controlul mașinii hardware. ○ Kernelul execută: Secvența de inițializare a componentelor hardware. Instanțierea principalelor componente (controlul proceselor, gestiunea memoriei, gestiunea fișierelor, etc.). Rămâne rezident în memorie, așteptând evenimente externe. Execută primul proces (ID = 1): /sbin/init. ○ init setează modul de operare (runlevel), definind starea mașinii după boot. Runlevel-urile sunt definite de un număr între 0 și 6 (în sistemele Unix istorice) și sunt configurate în /etc/inittab. init apelează scripturi de inițializare a serviciilor sistem (ex: /etc/rc0.d/, /etc/rc1.d, …, /etc/rc6.d, /etc/rcS.d). Runlevels ○ Runlevel-urile sunt asignate modului de operare al mașinii: 0: power-off 1: single-user mode 2: multi-user fără rețea 3: multi-user cu rețea, dar fără interfață grafică 4: nedefinit, rezervat pentru utilizări speciale 5: multi-user cu rețea și interfață grafică 6: reboot ○ Linux folosește systemd în loc de init, iar runlevel-urile sunt definite ca targets. ○ Comenzi pentru manipularea runlevel-urilor: runlevel: afișează runlevel-ul curent. telinit : comută sistemul în runlevel-ul specificat. Sisteme cu sau fără GUI ○ init este responsabil pentru pornirea proceselor de login: În funcție de runlevel: /sbin/getty sau desktop manager (xdm, gdm, etc.). Runlevel 3: init pornește getty pe terminale prestabilite. Runlevel 5: init pornește getty și desktop manager. Asocierea terminal-program de login se face în /etc/inittab în sistemele Unix istorice. ○ Comutarea între runlevel-uri cu și fără interfață grafică: telinit 3: dezactivează GUI. telinit 5: activează GUI. Combinații de taste (ex: Ctrl-Alt-F1 în Linux) permit comutarea între terminale și GUI, dar nu dezactivează GUI. Logarea Utilizatorului în Sisteme fără GUI ○ getty afișează promptul de login. ○ Utilizatorul introduce numele de utilizator. ○ getty apelează /bin/login pentru a stabili o nouă sesiune de lucru. ○ login afișează promptul de parolă. Caută în /etc/passwd o intrare corespunzătoare numelui de utilizator. Verifică parola (stocată criptat în /etc/shadow). Pentru parolă corectă, execută interpretorul de comenzi (shell) asociat. Asociază variabile de mediu (ex: USER, SHELL, HOME) cu shell-ul. ○ Shell-ul afișează un prompt specific (ex: $) și așteaptă comenzi. ○ init monitorizează sesiunea de lucru a utilizatorului și repornește getty la terminare. Interpretorul de Comenzi (CLI) ○ Command Line Interpreter (CLI) permite introducerea directă a comenzilor. Este un program de sistem care preia comenzile și le execută, fiind utilizat în mod interactiv sau batch (shell script-uri). Execută comenzi interne și externe. Asigură un mediu de lucru (comanda env), manipularea fișierelor, controlul programelor, activități I/O și administrarea sistemului. ○ Exemple de interpretoare de comenzi: Bourne Shell (/bin/sh), Bourne Again Shell (/bin/bash), C Shell (/bin/csh), Korn Shell (/bin/ksh). ○ /etc/shells conține interpretoarele disponibile. Interfața Grafică (GUI) ○ Este user-friendly, compusă din mouse, tastatură și monitor. ○ Icoanele reprezintă fișiere, programe, acțiuni. ○ Actionarea butoanelor mouse peste obiecte din interfață determină diverse acțiuni. ○ Multe sisteme includ atât CLI, cât și GUI. Microsoft Windows are GUI și CLI "command shell". Apple Mac OS X are GUI cu kernel UNIX dedesubt și shell-uri disponibile. Unix și Linux au CLI (shell-uri) cu GUI opțional (CDE, KDE, GNOME). Identificarea Utilizatorului ○ La login, utilizatorul primește un User ID (UID), o valoare întreagă nenegativă prin care este identificat în SO. UID este obținut din intrarea corespunzătoare din /etc/passwd, este unic și nu poate fi schimbat de utilizator. UID = 0 este rezervat pentru root sau superuser. Kernelul folosește UID pentru a verifica permisiunile proceselor. Procesele root au privilegii speciale și pot evita verificările kernelului. Este descurajată rularea programelor obișnuite ca root. ○ La login, utilizatorul primește și un Group ID (GID), setat de root în /etc/passwd. GID permite partajarea resurselor între membrii aceluiași grup. Intrările de director pentru fișiere conțin perechea (UID, GID) a proprietarului. Comanda ls -l afișează ID-urile proprietarului. ○ /etc/group asignează nume lizibile GID-urilor și este modificabil doar de root. Un utilizator poate avea mai multe GID-uri (supplementary GIDs). ○ Comanda /usr/bin/id afișează UID/GID. Fișiere și Directoare ○ Fișier: abstractizare pentru stocarea permanentă a datelor. Ascunde detaliile stocării fizice și prezintă datele ca un flux de octeți (în Unix). Grupate în directoare, referite prin nume. Atribute: tip, dimensiune, proprietar, permisiuni, timp de modificare. ○ Director/folder: colecție de fișiere și subdirectoare. Organizează informația ierarhic. Sistemele Unix folosesc o structură ierarhică cu directorul rădăcină /. ○ Directoare speciale: .: directorul curent. ..: directorul părinte. În directorul rădăcină,. și.. reprezintă același director /. ○ Cale (path): secvență de nume de fișiere separate prin /. Căi absolute: încep cu /. Căi relative: interpretate relativ la directorul curent. La login, directorul curent este setat la home directory-ul utilizatorului din /etc/passwd. ○ Comanda de afișare a intrărilor unui director: /bin/ls. Sistemul de Fisiere ○ Componentă a SO care gestionează fișierele și directoarele. ○ Structurează datele pe disc într-un format specific. ○ Ofera o interfață uniformă de acces la date. Exemplu: în Unix, o ierarhie arborescentă de directoare cu rădăcina comună. ○ SO moderne integrează sisteme de fișiere cu format diferit (Virtual Filesystem Switch - VFS). Discurile devin disponibile utilizatorului după operația de mount. Exemplu: mount -t ext4 /dev/sda1 /. ○ Directorul în care se montează discul se numește mountpoint. ○ /etc/fstab: tabela system-wide cu mountpoint-uri, inspectată la boot. La bootare, mountpoint-urile din tabelă se instalează cu mount -a. Descriptori de Fisiere ○ Numere întregi nenegative folosite pentru identificarea fișierelor deschise. Alocate de kernel la deschiderea/crearea unui fișier. Folosite de program pentru citire/scriere. ○ Descriptori speciali: 0: standard input 1: standard output 2: standard error Asociați cu terminalul de login sau terminalul de lucru. ○ Comanda /usr/bin/tty afișează terminalul asociat unui shell. Redirectarea Operațiilor de I/O ○ Se poate face programatic sau direct din shell. ○ Sintaxe de redirectare: [n] < filename: redirectează citirile de pe descriptorul n către fișier. filename: redirectează scrierile de pe descriptorul n către fișier. [n] >> filename: adaugă scrierile de pe descriptorul n la sfârșitul fișierului. ○ Exemple: echo "redirectarea stdout in fisierul out" > out echo "adaugam la sfarsitul fisierului out inca o linie" >> out cat < out cat > out mai adaugam o line la sfarsitul fisierului out EOF CURSUL 3 Introducere Cursul 3 se concentrează pe interpretatorul de comenzi, fișiere și directoare, revizitând concepte deja discutate. Materialul este structurat astfel: interpretorul de comenzi, și o revizuire a conceptelor legate de fișiere și directoare. Interpretorul de comenzi (recapitulare) Interpretorul de comenzi funcționează în două moduri: ○ Mod interactiv: utilizatorul introduce o comandă, iar sistemul oferă un răspuns imediat. ○ Mod batch: comenzile sunt grupate în scripturi pentru a automatiza sarcinile. În modul interactiv, interpretorul afișează un prompt, care indică faptul că așteaptă o comandă de la utilizator. ○ Prompt-ul uzual este $ sau % pentru utilizatorii obișnuiți și # pentru utilizatorul root. ○ Acest prompt este definit de conținutul variabilei de mediu PS1. Promptul de continuare este specificat în variabila de mediu PS2, de obicei >. Mediul de lucru (environment) Mediul de lucru este o listă de perechi nume = valoare. Numele este numele unei variabile interne a shell-ului. ○ Nu orice variabilă internă a shell-ului este și variabilă de mediu. Valorile variabilelor influențează comportamentul shell-ului și al comenzilor externe lansate de acesta. ○ Variabilele pot fi setate de sistemul de operare sau de utilizator. Numele variabilelor de mediu sunt scrise cu litere mari, de exemplu: PS1, SHELL, HOME, PATH. Valoarea unei variabile de mediu este accesată folosind simbolul $, de exemplu: $SHELL = /bin/bash. Variabile de mediu Variabilele de mediu sunt setate cu comanda internă export. ○ Aceasta marchează variabila ca fiind variabilă de mediu. ○ Exemplu: $ export PS1=“my-new-prompt> ” Variabilele de mediu sunt afișate cu comanda /usr/bin/env. Într-un program C, variabilele de mediu sunt accesibile prin al treilea parametru al funcției main. ○ Exemplu: int main(int argc, char* argv[], char *envp[]) The Bourne-Again Shell (bash) /bin/bash este succesorul primului shell istoric, /bin/sh (Bourne Shell). Fișierele de configurare sunt: ○ Fișiere de start-up, inspectate doar la login. La nivel de sistem: /etc/profile. La nivel local (în directorul home): ~/.profile, ~/.bash_profile, ~/.bash_login. Conținutul lor este executat automat la login. ○ Fișiere de start-up inspectate la crearea fiecărui terminal (rc file). ~/.bashrc. Conținutul lor poate fi executat voluntar cu comanda source (sau.). Exemplu: source.bashrc. ○ Fișier de logout: ~/.bash_logout. Conținutul este executat la ieșirea din shell (cu exit sau Ctrl-d). Ctrl-d în Unix este caracterul EOF, care, introdus la prompt, termină shell-ul. Istoricul comenzilor este înregistrat în ~/.bash_history. Structura comenzilor bash Pipeline-uri: ○ $ cmd1 | cmd2 | … |cmdn - execută comenzile în paralel. ○ $ cmd1 |& cmd2 |& … |& cmdn - |& este echivalent cu 2>&1 |. Liste de comenzi: ○ $ cmd1; cmd2; …; cmdn - execută comenzile secvențial. ○ $ cmd1 && cmd2 && … && cmdn. ○ $ cmd1 || cmd2 …. || cmdn. Variabila bash ? conține codul de terminare (exit status) al ultimei comenzi executate. ○ Valoarea zero indică succesul. ○ Exemplu: $ echo $?. ○ Variabila ? nu este o variabilă de mediu. Job control Programele se împart în două categorii: ○ Executate în foreground, având acces R/W la terminal. ○ Executate în background. O comandă terminată cu & rulează în background, iar shell-ul returnează imediat promptul. ○ Exemplu: $ cmd &. Execuția unei comenzi în foreground poate fi suspendată cu Ctrl-z (semnalul SIGTSTP). Execuția comenzii suspendate poate fi reluată, fie în foreground, fie în background. Comanda jobs listează procesele (job-urile) rulate de shell. ○ Joburile sunt identificate printr-un număr. ○ Numărul job-ului poate fi folosit cu următoarele comenzi: $ kill %n - termină procesul/job-ul cu numărul n. $ fg %n - mută în foreground procesul cu numărul n. $ bg %n - mută job-ul n în background. $ %n & - mută job-ul n în background. Controlul istoricului comenzilor Istoricul comenzilor este stocat în fișierul ~/.bash_history. Exemple de utilizare a istoricului comenzilor: ○ !n - re-execută comanda cu numărul n. ○ !-n - re-execută comanda curentă minus n. ○ !string - re-execută cea mai recentă comandă care începe cu string. ○ !?string? - re-execută cea mai recentă comandă care conține string. ○ ^str1^str2 - repetă comanda anterioară înlocuind str1 cu str2. ○ În mod interactiv: Ctrl-r urmat de un substring al comenzii căutate din istoric. Comenzi Interne: executate direct de bash. ○ Exemple: cd , alias l=‘ls –l’, fg/bg/kill , exit , exec. ○ exec înlocuiește imaginea bash cu imaginea noului proces. Externe: programe de pe disc lansate de shell. ○ Exemple: pwd, echo string. ○ Comanda echo poate folosi caractere escape: echo –e \a (bell), echo –e “aaa\tbbb” (tab orizontal), etc.. Tipuri de fișiere Fișiere obișnuite (regular files): conțin date (text sau binare). Directoare: conțin numele altor fișiere și informații despre ele. ○ Pot fi citite de procesele care au permisiunile potrivite. ○ Doar kernel-ul poate scrie în ele. Fișiere speciale, tip device: ○ Caracter: pentru dispozitive caracter (ex: tty, seriala). ○ Bloc: pentru dispozitive orientate pe bloc (ex: discuri). ○ Operațiile de R/W se fac prin intermediul driverelor, nu al sistemului de fișiere. ○ Orice dispozitiv din sistem este fie fișier bloc, fie caracter. FIFO: named pipe, mecanism IPC (Inter-Process Communication). ○ Sunt fișiere de pe disc, cu nume și politică de acces FIFO. ○ Bidirecționale, spre deosebire de pipe-urile anonime (|). Socket: abstracție pentru IPC peste rețea. ○ Canal de comunicare local (socket Unix, un fel de FIFO). ○ Canal de comunicare între mașini conectate în rețea (socket TCP/IP). Link simbolic: fișier care referă un alt fișier. ○ Practic, conține numele fișierului sursă. ○ Creat cu comanda ln -s. Identificarea tipurilor de fișiere Formatul lung al comenzii ls marchează tipul fișierului cu primul caracter: -, d, c, b, p, s, l. Comanda generală file distinge și alte tipuri de fișiere regulate (text, executabile, imagini etc.). ○ Exemplu: $ file. Set UID, set GID Fiecare proces are asociat: ○ UID, GID real: identitatea reală a utilizatorului, provenită din /etc/passwd. ○ UID, GID efectiv. ○ set-UID, set-GID salvate (copii ale UID/GID efectiv). În mod normal, UID/GID real = UID/GID efectiv. La executarea unui program, se poate seta un flag în atributele fișierului executabil, astfel încât UID/GID efectiv al procesului devine UID/GID-ul proprietarului fișierului. ○ Exemplu: comanda passwd este set-UID la root pentru a avea drepturi de scriere în /etc/shadow. Permisiuni de acces la fișiere Atributele fișierului sunt grupate în trei categorii: ○ Permisiuni utilizator: S_IRUSR, S_IWUSR, S_IXUSR. ○ Permisiuni grup: S_IRGRP, S_IWGRP, S_IXGRP. ○ Permisiuni pentru alți utilizatori: S_IROTH, S_IWOTH, S_IXOTH. ○ Permisiuni speciale: set-uid, set-gid, sticky bit. Modificabile cu comanda chmod. ○ Exemple: chmod u+rw , chmod g-x , chmod o-rwx , sau chmod 755 , chmod 644. Accesul la un fișier este condiționat de combinația dintre UID/GID efectiv al comenzii executate și biții de permisiune. umask Orice fișier nou creat are setată o mască implicită a permisiunilor, setată cu comanda umask. ○ Exemplu: $ umask 022. Biții setați în umask sunt off în permisiunile noului fișier creat. De obicei, masca este setată în fișierele de configurare shell (ex: /etc/profile). Ștergerea fișierelor Un fișier poate avea mai multe link-uri la aceeași structură internă din kernel (i-node), numite link-uri hard. ○ Create cu comanda ln. ○ Exemplu: $ ln. Ștergerea unui link nu înseamnă ștergerea fișierului de pe disc. Ștergerea ultimului link șterge și fișierul. Pentru a șterge o intrare de fișier dintr-un director se folosește comanda rm. ○ Exemplu: $ rm. Ștergerea necesită două permisiuni: de a scrie în director și de a căuta în director (bitul x de execuție setat în director). Link-uri simbolice Limitările link-urilor hard: ○ Link-ul și fișierul legat trebuie să fie pe același sistem de fișiere. ○ Doar root poate crea link-uri hard către directoare. Link-ul simbolic este un fișier care conține numele fișierului referit (un string). Sunt folosite pentru a ocoli limitările link-urilor hard. Create cu comanda ln -s. ○ Exemplu: $ ln –s /etc/profile ~/.system-wide-profile. Comenzile shell, în general, dereferențiază link-ul simbolic, cu excepția: lstat, remove, rename, unlink, etc. ○ Exemplu: $ rm ~/.system-wide-profile (șterge link-ul simbolic, nu sursa, adică /etc/profile). ○ $ ls -l ~/.system-wide-profile (afișează atributele linkului simbolic, nu ale sursei). ○ $ cat ~/.system-wide-profile (afișează conținutul /etc/profile). Lucrul cu directoare Create cu mkdir, șterse cu rmdir. ○ Exemple: $ mkdir , $ mkdir –p / (creează directoarele inexistente). ○ rmdir nu poate șterge un director decât dacă este gol. Schimbarea directorului curent: ○ $ cd (schimbă directorul în ). ○ $ cd (echivalent cu $ cd $HOME). ○ $ cd - (schimbă directorul curent în directorul anterior). Aflarea directorului curent de lucru (current working directory): $ pwd. CURSUL 4 Introducere Cursul 4 acoperă fișiere și directoare (epilog), procese, comunicarea inter-procese (IPC), și semnale. Fișiere și directoare (epilog) Sunt revizuite câteva comenzi utile pentru lucrul cu fișiere: ○ mkdir - creează directoare. ○ rmdir - șterge directoare (cu condiția să fie goale). ○ touch - creează un fișier gol dacă nu există deja. ○ mv - mută directoare sau fișiere, redenumind în același timp dacă este cazul, dar nu se face o copiere fizică decât dacă datele se mută de pe un disc pe altul. ○ cp - copiază (fizic, duplică) directoare (cu opțiunea -r) sau fișiere, putând copia mai multe fișiere/directoare într-un director destinație. Exemplu: $ cp ….. ○ rm - șterge directoare (cu opțiunea -r) sau fișiere. ○ ln - creează link-uri hard sau simbolice. ○ mknod - creează fișiere speciale tip caracter, bloc sau FIFO. Exemplu: $ mknod /dev/sda3 b 8 3. Sunt introduse wildcards, caractere speciale interpretate de shell: ○ ^ - simbolizează începutul liniei. ○ $ - simbolizează sfârșitul liniei. ○ Atom - un caracter sau un set de caractere grupate cu [] sau (). ○ * - 0 sau mai multe apariții ale atomului precedent. ○ + - cel puțin 1 apariție a atomului precedent, posibil mai multe. ○ ? - cel mult o apariție a atomului precedent (0 sau 1 apariții). Căutarea în fișiere Comanda uzuală este grep, care folosește tipare și expresii regulate. ○ Sintaxa generală: $ grep. ○ Opțiuni utile: -R / -r - căutare recursivă (cu sau fără dereferențiere link-uri simbolice). -i - căutare case-insensitive. -n - tipărește numărul liniei pe care s-a găsit expresia. -w - caută cu exactitate tiparul furnizat (cuvânt). -v - inversează sensul matching-ului (afișează liniile care nu se potrivesc). ○ Exemple: $ grep printf *.c. $ grep –v –w printf *.[ch]. $ ls –l | grep ^d. Căutarea în directoare Comanda uzuală este find. ○ Sintaxa generală: $ find -name. ○ Opțiuni utile: -exec - execută o comandă asupra elementelor găsite. -type - limitează rezultatele afișate la un anumit tip (ex, fișiere). -iname - similar cu -name, dar case-insensitive. -maxdepth - limitează nivelul de recursivitate. ○ Exemple: $ find / -name hello. $ find. –iname \*.o –exec rm {} \;. Procese Un proces este o abstracție a execuției unui program (instrucțiuni + date). Este programul plus starea execuției sale la un moment dat (reflectată de registrele CPU și valorile variabilelor din program). Fiecare proces este identificat printr-un Process ID (PID). Comanda ps afișează PID-urile proceselor aflate în rulare. Mai multe instanțe ale aceluiași program sunt procese diferite, cu PID-uri diferite. Execuția proceselor este secvențială, nu există execuție paralelă a instrucțiunilor într-un singur proces. Un proces are mai multe părți: ○ Codul program (secțiunea de text). ○ Starea curentă reflectată de registrele CPU. ○ Stiva (date temporare, parametri funcțiilor, adrese de retur, variabile locale). ○ Secțiunile de date inițializate/neinițializate (datele globale). ○ Heap-ul (memoria alocată dinamic de program în timpul execuției). Este prezentată imaginea unui program C în memorie, cu break, variabile de mediu, program. Comunicarea Inter-Procese (IPC) Procesele pot fi independente sau cooperante. Procesele cooperante pot afecta sau pot fi afectate de alte procese, inclusiv prin partajarea datelor. Motive de cooperare: ○ Partajarea informației. ○ Accelerarea calculului. ○ Modularitate. ○ Confort. Procesele cooperante necesită mijloace de comunicare inter-proces (IPC). Modele IPC: ○ Memorie partajată. ○ Schimb de mesaje (message passing). Modele de comunicare Message passing: procesele comunică fără variabile partajate. ○ Operații: send(message). receive(message). ○ Dimensiunea mesajului poate fi fixă sau variabilă. Tipuri de comunicare: ○ Directă: procesele își folosesc identitatea explicit. send (P, message) - trimite un mesaj procesului P. receive(Q, message) - primește un mesaj de la procesul Q. Exemplu: sockets (canale de comunicatie TCP/IP). ○ Indirectă: mesajele sunt trimise și recepționate în/din căsuțe poștale (porturi). Fiecare căsuță are un ID unic. Procesele comunică doar dacă partajează o căsuță. Operații: creează căsuță, trimite/primește mesaje, șterge căsuță. Primitive de comunicare: send(A, message) - trimite mesaj în căsuța poștală A. receive(A, message) - primește mesaj din căsuța poștală A. Sincronizare Schimbul de mesaje poate fi blocant sau neblocant. Modul blocant (sincron): ○ send blocant: transmițătorul e blocat până când se primește mesajul. ○ receive blocant: receptorul e blocat până când un mesaj e disponibil. Modul neblocant (asincron): ○ send neblocant: transmițătorul trimite mesajul și continuă. ○ receive neblocant: receptorul primește un mesaj valid sau un mesaj vid (null). Diferite combinații sunt posibile; dacă send și receive sunt ambele blocante, avem un rendezvous. Comunicare FIFO în Unix Prin pipe-uri anonime sau cu nume. Pipe-uri anonime: ○ Combinație de comunicare directă/indirectă. ○ Procesele cooperante își cunosc implicit identitatea. ○ Comunicare unidirecțională. ○ Exemplu: $ cat hello.c| grep printf. Pipe-uri cu nume (FIFOs): ○ Fișiere speciale cu nume. ○ Comunicare indirectă, procesele cooperante nu își cunosc identitatea. ○ Create cu comenzile mknod/mkfifo. ○ Folosite ca fișiere, dar cu politică de acces FIFO. Exemplu: $ mknod myfifo p (echivalent cu mkfifo myfifo). $ cat < myfifo & (trebuie să existe mai întâi un receptor care așteaptă date). $ echo “write some message in myfifo” > myfifo. Semnale Semnalele sunt notificări asincrone ale procesului referitoare la producerea anumitor evenimente. Echivalentul software al excepțiilor (HW sau SW). Se trimit fie între procese, fie de către kernel către un proces. Generate din mai multe surse: ○ Apel sistem kill(pid, semnal). ○ Comanda kill: kill –TERM. ○ Tastatură: DEL, Ctrl-C, Ctrl-Z, etc. ○ Anumite evenimente soft și hard generate de kernel. Exemple: ○ Terminarea unui proces notificată asincron părintelui cu SIGCHLD. ○ Procesul care execută o împărțire la zero primește SIGFPE. ○ Accesul ilegal la memorie (memorie nealocată) generează SIGSEGV. Reacția procesului la primirea unui semnal depinde de tipul semnalului și de decizia programului de a trata sau nu evenimentul. Posibilități de tratare a semnalelor Semnalul este ignorat (pentru evenimente care nu rezultă în erori majore). Terminarea programului (semnalul "ucide" procesul). Tratarea semnalului conform indicației programului, se spune că "prinde" semnalul (cu ajutorul unui handler). Nu orice semnal poate fi "prins"! De exemplu, SIGKILL/SIGSTOP nu pot fi prinse. ○ $ kill -KILL (echivalent cu kill -9 ). Exemple utilizare semnale Comanda kill: ○ Folosește un PID identificat cu ps. ○ $ kill –. ○ $ kill –TERM 4899 (echivalent cu kill 4899 sau kill -15 4899). ○ Numele semnalului poate fi complet (ex, SIGTERM) sau prescurtat (ex, TERM). ○ $ kill –l (afișează toate semnalele disponibile). ○ $ kill –l 15 (mapează numărul de semnal în nume). Semnalele pot fi generate voluntar de către utilizator. ○ Ctrl-c generează SIGINT (uzual termină procesul rulat de shell). Dacă procesul prinde SIGINT, la apăsarea Ctrl-c se execută handlerul asociat (procesul nu moare automat). $ kill –SIGINT 4899 (echivalent cu kill -2 4899). ○ Ctrl-z generează SIGTSTP (suspendă execuția procesului curent). Poate fi continuat cu comenzi de job control (fg/bg). $ kill –SIGTSTP 4899 (echivalent cu kill -20 4899). CURSUL 5-6 Introducere în Shell Scripting Scopul Shell Scripting: Shell scripting reprezintă scrierea de programe într-un mediu specific, numit shell, cu scopul de a automatiza sarcini și secvențe de comenzi. În esență, un script shell transformă o serie de comenzi, care ar fi executate manual de un utilizator, într-un program automatizat. Aceasta permite o gestionare mai eficientă a sarcinilor, mai ales când vine vorba de operații repetitive sau complexe. Natura Interpretată a Scripturilor: Scripturile shell nu necesită compilare. În loc să fie transformate în cod mașină printr-un compilator, ele sunt executate direct din codul sursă de un program numit interpretator. Acest interpretor citește și execută instrucțiunile scriptului linie cu linie. Aplicații și Motivații: ○ Automatizare: Scripturile sunt folosite extensiv pentru a automatiza operații de configurare, administrare a sistemului, pornire/oprire de servicii, și alte sarcini repetitive. ○ Execuție Secvențială: Ele permit executarea unui șir de comenzi printr-o singură comandă, simplificând interacțiunea cu sistemul. ○ Dezvoltare Rapidă: Sunt ideale pentru dezvoltarea rapidă a programelor scurte, în general, fiind mai orientate spre comenzi shell și de sistem decât spre operații logice sau aritmetice complexe. ○ Portabilitate: Un aspect important este portabilitatea scripturilor, acestea fiind concepute să funcționeze pe diverse sisteme pentru a automatiza operații de configurare și administrare. Totuși, utilizarea intensivă a bash a generat o anumită lipsă de portabilitate. Variante de Shell Diversitatea Shell-urilor: Există mai multe implementări de shell, fiecare cu particularitățile ei. ○ sh (Bourne shell): Unul dintre primele shell-uri, prezent în /bin/sh, cu funcționalitate redusă dar foarte portabil. ○ csh (C shell): Oferă comenzi similare cu cele din limbajul C. ○ ksh (Korn shell): Este bazat pe sh și este considerat un succesor al csh. ○ bash (Bourne Again shell): Cel mai utilizat shell, fiind disponibil inclusiv în Windows 10. Majoritatea scripturilor moderne sunt scrise în bash. Variabile în Shell Tipuri de Variabile: Există două categorii principale de variabile: ○ Variabile Locale: Acestea există doar în instanța curentă a shell-ului. Prin convenție, se scriu cu litere mici. Asignarea se face fără spații, de exemplu x=1. Dacă se folosesc spații, de exemplu x = 1, comanda este interpretată ca și cum am apela comanda x cu argumentele = și 1. ○ Variabile de Mediu: Sunt folosite de sistem pentru a defini modul de funcționare al programelor. Shell-ul trimite aceste variabile de mediu proceselor sale fiice. Exemple importante sunt $HOME, $PATH, $SHELL, $EDITOR și $LANG. Utilizarea Variabilelor: ○ Valoarea unei variabile este accesată prin prefixarea numelui cu $ (ex: echo $x). ○ Comanda env afișează toate variabilele de mediu definite. ○ Comanda export este folosită pentru a seta o variabilă de mediu. ○ Comanda printenv este folosită pentru a afișa valoarea unei variabile de mediu. Expansiunea Variabilelor: ○ $(cmd): Evaluează comanda cmd și rezultatul devine valoarea variabilei. De exemplu, $(pwd) returnează directorul curent. ○ $((expr)): Evaluează expresia aritmetică expr, inclusiv cu efecte secundare. De exemplu, echo $((1+1)) afișează 2, iar $((x++)) incrementarea lui x. Citarea (Quoting) Interpretarea Șirurilor de Caractere: Modul în care sunt interpretate șirurile de caractere depinde de tipul de citare folosit. ○ Single Quotes ('): Toate caracterele își păstrează valoarea literală. Chiar și caracterul $ este tratat ca atare, nu ca un prefix pentru variabile. Singura excepție este caracterul ' care nu poate fi inclus. De exemplu, echo 'Am o variabilă $x' va afișa exact acel text. ○ Double Quotes ("): Permite interpretarea caracterelor speciale precum $, \, și ``, restul caracterelor fiind tratate literal. De exemplu, echo "$USER are home in $HOME" va afișa numele utilizatorului și directorul său home. ○ Back Quotes (`): Funcționează similar cu $(), evaluând comanda din interior. De exemplu, echo "Today isdate" va afișa data și ora curentă. Înlănțuirea Comenzilor Modalități de Înlănțuire: Comenzile pot fi înlănțuite pentru a executa mai multe operații într-o singură linie. ○ ; (secvențială): Execută comenzile una după alta, indiferent de succesul sau eșecul comenzii precedente (ex: cmd1; cmd2). ○ | (pipe): Ieșirea unei comenzi devine intrarea celei de-a doua (ex: cmd1 | cmd2). ○ && (condiționată - succes): Execută a doua comandă doar dacă prima s-a executat cu succes (ex: cmd1 && cmd2). ○ || (condiționată - eșec): Execută a doua comandă doar dacă prima a eșuat (ex: cmd1 || cmd2). Scripting (Continuare) Structura Scripturilor: ○ Linia Shebang: Scripturile încep cu #! urmat de calea către interpretorul (ex: #!/bin/sh sau #!/usr/bin/env python). env este folosit pentru a asigura portabilitatea, căutând interpretorul în variabilele de mediu. ○ Comentarii: Liniile care încep cu # sunt considerate comentarii și sunt ignorate de interpretor. Execuția Scripturilor: ○ Permisiuni: Scripturile trebuie să aibă permisiunea de execuție (chmod +x script.sh). ○ Execuție Directă: Pot fi executate cu./script.sh sau cu sh script.sh (caz în care nu mai e nevoie de permisiunea de execuție). Variabile Speciale în Scripturi (Continuare) Argumente și Stare: ○ $1, $2,...: Reprezintă argumentele scriptului, în ordinea în care sunt primite. Dacă numărul argumentului are mai mult de două cifre, trebuie pus între acolade (ex: ${10}). ○ $0: Numele scriptului (ex: hello.sh). ○ $#: Numărul de argumente primite. ○ $*: Toate argumentele, ca un singur șir (ex: "$1 $2... $n"). ○ $@: Toate argumentele, ca o listă de șiruri individuale (ex: "$1" "$2"... "$n"). ○ $?: Valoarea de ieșire a ultimei comenzi executate (0 pentru succes, diferit de 0 pentru eșec). ○ $$: ID-ul procesului curent. ○ $!: ID-ul ultimului proces suspendat. ○ shift: Mută parametrii poziționali spre stânga, adică $2 devine $1, $3 devine $2 și așa mai departe. Blocuri de Control (Continuare) Condiționale ○ if: Structura este if test-cmd; then cmds; elif test-cmd; then cmds; else cmds; fi. Rezultatul lui test-cmd este stocat în $?. ○ test sau []: Folosite pentru comparații sau verificări. Spațiile sunt foarte importante (ex: [ expr ]). [ este de fapt o comandă internă a shell-ului. Operatori logici: -a (și logic), -o (sau logic), ! (negație). Operatori numerici: -eq (egal), -ne (diferit), -ge (mai mare sau egal), -gt (mai mare), -le (mai mic sau egal), -lt (mai mic). Operatori șiruri: -n (lungimea șirului diferită de 0), -z (șir gol), = sau == (egalitate), != (diferit). Operatori fișiere: -e (calea există), -f (fișier obișnuit), -d (director), -r (permisiune de citire), -w (permisiune de scriere), -x (permisiune de execuție). Iterative ○ while: while cmd; do cmds; done. Execută comenzile cât timp cmd are succes. Se poate folosi și o expresie de test în locul comenzii. ○ until: until cmd; do cmds; done. Execută comenzile cât timp cmd eșuează. Se poate folosi și o expresie de test în locul comenzii. ○ for: for var in str1 str2... strN; do cmds; done. Iterează prin lista de șiruri, atribuind fiecărui șir lui var. Există și o formă tradițională, similară cu for din C, dar aceasta nu este portabilă. case: Similar cu switch din C. Structura este case var in pattern1) cmds;; pattern2) cmds;; *) defaultcmd;; esac. pattern poate fi un string sau o expresie shell (similar cu wildcards din grep). Funcții (Continuare) Modalități de Returnare: ○ Pot modifica variabile globale. ○ Pot folosi exit pentru a încheia scriptul. ○ Pot folosi return pentru a încheia funcția. ○ Pot trimite date la stdout, care pot fi recuperate de apelant folosind backticks (``) sau $() (ex: var=$(expr...) ). Parametri și Scop: ○ Nu pot modifica parametrii de apel, dar pot modifica variabile globale. ○ Cu excepția parametrilor, nu există domeniu de vizibilitate (scope) pentru variabile. Recursivitatea: Funcțiile pot fi recursive, adică se pot autoapela. Biblioteci de Funcții (Continuare) Structura: O colecție de funcții grupate într-un fișier care nu începe cu #!. Variabile Globale: Pot defini variabile globale. Apelul: Se folosesc comenzile source sau. (ex: source renamelib.sh sau. renamelib.sh). Coduri de Retur (Continuare) Funcțiile pot returna coduri de retur folosind comanda return. Codul de retur al ultimei comenzi este stocat în variabila $?. Comanda read (Continuare) Citirea de la Intrare: ○ Sintaxa este read var1 var2... varN. Citește valori de la intrare și le atribuie variabilelor specificate. ○ Dacă nu se specifică variabile, tot ce se citește este stocat în $REPLY. Citirea Linie cu Linie: Poate fi folosită pentru a citi un fișier linie cu linie. Depanare (Continuare) Opțiunea -x: Se apelează scriptul cu opțiunea -x (ex: sh -x script.sh). Comenzile executate sunt afișate pe ecran, prefixate cu +. CURSUL 7 Acest curs se concentrează pe instrumentele și tehnicile fundamentale utilizate în informatică, în special în ceea ce privește procesarea textului într-un mediu de linie de comandă. Principalele subiecte abordate sunt filtrele, editarea automată a textelor și procesarea automată a textelor. 1. Filtre Un filtru este un program, o comandă sau o operație care procesează ieșirea text a unei alte comenzi, astfel încât noua formă să poată fi prelucrată mai departe de utilizator sau de un alt program. Scopul este de a transforma datele într-o formă mai utilă sau specifică. Linii, Separatori și Câmpuri: ○ O linie este un șir de caractere terminat cu \n (sau \r\n în Windows). ○ Un separator (sau delimitator) este un caracter sau un șir folosit pentru a delimita datele dintr-o linie. ○ Un câmp este un subșir dintr-o linie care reprezintă un anumit tip de date. ○ De exemplu, o linie ar putea fi structurată ca nume prenume grupă serie, unde caracterul spațiu " " acționează ca separator, iar nume, prenume, grupă și serie sunt considerate câmpuri. 2. Comanda cut(1) Comanda cut(1) este folosită pentru a extrage câmpuri din fiecare linie primită ca intrare. Iată o defalcare a funcționalităților sale: Scop: Extrage secțiuni specifice de text (câmpuri, caractere sau octeți) din liniile de intrare. Opțiuni: ○ -b listă: Specifică o listă de poziții de octeți pentru a extrage. ○ -c listă: Specifică o listă de poziții de caractere pentru a extrage. ○ -f listă: Specifică o listă de câmpuri pentru a extrage. ○ -d delim: Specifică delimitatorul pentru câmpuri (implicit este \t, caracterul tab). ○ -n: Evită împărțirea caracterelor multi-byte în octeți. ○ -s: Omite liniile care nu conțin delimitatoare. Tipuri de Apel: ○ cut -b [-n] listă [fișier...] ○ cut -c listă [fișier...] ○ cut -f listă [-s] [-d delim] [fișier...] Exemple: ○ cut -d : -f 1,7 /etc/passwd: Afișează numele de utilizator și shell-urile folosite de utilizatorii din sistem, folosind : ca delimitator și extrăgând primul și al șaptelea câmp. ○ who | cut -c 1-8,18-30: Arată numele de utilizator și datele de autentificare din ieșirea comenzii who, extrăgând pozițiile caracterelor de la 1 la 8 și de la 18 la 30. 3. Comanda paste(1) Comanda paste(1) este utilizată pentru a lipi fișierele primite ca intrare pe coloane (pe verticală). Scop: Unește liniile mai multor fișiere, alăturându-le. Opțiuni: ○ -d listă: Folosește un delimitator pentru a înlocui caracterul linie nouă \n din fiecare fișier. ○ -s: Serializare, lipind toate liniile fiecărui fișier una după alta. ○ -: Reprezintă intrarea standard (stdin). Apel: paste [-s] [-d listă] fișier... Exemple: ○ paste prenume.txt nume.txt: Lipește conținutul fișierelor prenume.txt și nume.txt unul lângă altul. ○ paste -s prenume.txt nume.txt: Serializare, afișând toate numele din prenume.txt, urmate de toate numele din nume.txt. ○ ls | paste - - -: Afișează fișierele din directorul curent pe trei coloane. ○ find / -name bin -type d | paste -s -d : -: Creează o listă de directoare bin separate prin :. 4. Comanda split(1) Comanda split(1) împarte un fișier dat în mai multe fișiere, creând implicit fișiere de câte 1000 de linii fiecare. Scop: Împarte un fișier în părți mai mici. Opțiuni: ○ -a sufix_lungime: Setează numărul de litere din sufixul noilor fișiere. ○ -b număr_octeți: Creează fișiere de lungimea specificată în octeți. ○ -l număr_linii: Creează fișiere cu numărul de linii specificat. ○ fișier: Fișierul de împărțit, implicit este stdin. ○ nume: Prefixul pentru noile fișiere. Apel: split [opțiuni] [fișier [nume]] Exemple: ○ split -l 100 fisier.tex: Împarte fisier.tex în fișiere cu câte 100 de linii fiecare. ○ split -a 1 -l 100 fisier.tex fisier: Împarte fisier.tex cu un prefix de fișier fisier și un sufix de o singură literă. 5. Comanda join(1) Comanda join(1) alătură liniile din două fișiere diferite care conțin chei identice. Scop: Alătură linii din două fișiere pe baza unui câmp comun. Opțiuni: ○ -1 câmp: Specifică câmpul cheie din primul fișier. ○ -2 câmp: Specifică câmpul cheie din al doilea fișier. ○ -a număr_fișier: Produce o linie pentru fiecare nepotrivire din fișierul specificat (1 sau 2). Apel: join [-1 câmp] [-2 câmp] [opțiuni] fișier1 fișier2 Exemple: ○ join age.txt income.txt: Alătură liniile din age.txt și income.txt pe baza primului câmp. ○ join -a1 age.txt income.txt: Alătură liniile din age.txt și income.txt, dar include și liniile din age.txt chiar dacă nu au o potrivire în income.txt. 6. Comanda bc(1) (Basic Calculator) Comanda bc(1) este un calculator pentru operații aritmetice și logice. Scop: Oferă un calculator de linie de comandă. Opțiuni: ○ -l: Permite operații cu numere în virgulă mobilă. ○ -e expr: Evaluează expresia (expresiile). ○ fișier: Prelucrează expresiile din fișierul dat. Funcții: ○ s(x): sinus. ○ c(x): cosinus. ○ e(x): exponențial. ○ l(x): logaritm. ○ a(x): arctangent. ○ sqrt(x): radical. ○ scale=n: setează precizia la n zecimale. ○ quit: termină programul. Apel: bc [-l] [-e expr] [fișier] Exemple: ○ echo "1/3" | bc: Împărțire de bază, rezultatul este 0. ○ echo "1/3" | bc -l: Împărțire cu rezultat în virgulă mobilă: 0.33333333333333333333. ○ bc -l -e "sqrt(2)" -e quit: Calculează radicalul lui 2. 7. Comanda tr(1) (Translate) Comanda tr(1) traduce caracterele primite de la stdin și afișează rezultatul la stdout. Scop: Traduce, șterge sau elimină caractere duplicate. Opțiuni: ○ -C, -c: Aplică complementul setului de caractere din șir1. ○ -d: Șterge caracterele care apar în șir1. ○ -s: Elimină duplicatele conform ultimului operand (fie șir1, fie șir2). Apel: ○ tr [-Ccs] șir1 șir2 ○ tr [-Cc] -d șir1 ○ tr [-Cc] -s șir1 Exemple: ○ echo "Ana are mere" | tr -cs "[A-Za-z]" "\n": creează o listă de cuvinte. ○ echo "Ana are mere" | tr "[a-z]" "[A-Z]": convertește intrarea în majuscule. ○ echo "int main() { return 0; }" | cc -xc -o test -; cat test | tr -cd "[:print:]": extrage șiruri de caractere printabile dintr-un fișier binar. 8. Comanda sed(1) (Stream EDitor) Comanda sed(1) este un editor de text complet și chiar un limbaj de programare. Scop: Manipularea textului, în special pentru substituții și ștergeri folosind expresii regulate. Funcționalitate: ○ Procesează intrarea linie cu linie, căutând un tipar. ○ Dacă un tipar este găsit, aplică o funcție asupra acestuia. ○ Funcțiile pot fi predefinite (substituție, ștergere) sau scrise de utilizator. Apel: sed [opțiuni] comandă [fișier...] Exemple: ○ echo "Paul Alex Ana" | sed 's/Alex/Paul/': Înlocuiește "Alex" cu "Paul". ○ echo "Paul Alex Alex Ana" | sed 's/Alex/Paul/g': Înlocuiește toate instanțele lui "Alex" cu "Paul". ○ echo "Paul Alex\nAlex Ana" | sed '/Paul/d': Șterge liniile care conțin "Paul". ○ echo "Paul Alex\nAlex Ana" | sed 's/Paul//g': Șterge "Paul" din orice linie. ○ echo "Paul\nAlex\nAlex\nAna\nPaul\nGeorge" | sed '1,3 s/Paul//g': aplică substituția doar liniilor 1, 2 și 3. ○ echo "Paul Irofti\nAlex Pop\nGeorge Stan" | sed 's/^\([A-Z][A-Za-z]*\) \([A-Z][A-Za-z]*\)/\2 \1/': Inversează două cuvinte de pe fiecare linie. ^: Caută un tipar la începutul unei linii. [A-Z]: Trebuie să înceapă cu o literă majusculă. [A-Za-z]*: Poate continua cu oricâte litere mici sau mari. (): Demarcă două expresii într-un tipar. \1, \2: Șirurile găsite cu cele două expresii. 9. Comanda awk(1) Comanda awk(1) este un limbaj de programare specializat pentru procesarea datelor de tip text. Scop: Scanarea tiparelor și procesarea textului. Funcționalitate: ○ Funcționează pe principiul identificării tiparului urmată de aplicarea funcției, similar cu sed(1). ○ Verifică mai mult de un tipar. ○ Verifică linia curentă cu fiecare tipar dat, apoi trece la următoarea linie. ○ Este Turing Complete. Apel: awk [opțiuni] [program] fișier... Exemple: ○ echo "Paul Irofti\nAlex Pop\nGeorge Stan" | awk '/Pop/{print}': Afișează liniile care conțin "Pop". ○ echo "Doris si Nemo\nNemo la dentist\nDoris-a pierdut" | awk 'BEGIN {print "Finding Nemo and Dori"} /[Nn]emo/ {nemo++} /[Dd]ori/ {dori++} END {print "Found Nemo " nemo " times and Dori " dori " times!" }': Numără de câte ori apar "Nemo" și "Dori". Comenzile BEGIN și END se execută o singură dată. ○ cat cont.txt: Afișează un exemplu de procesare a câmpurilor dintr-un fișier. ○ awk 'BEGIN {print "Fonduri disponibile"; fonduri=0} /IN/ {fonduri+=$2} /OUT/ {fonduri-=$2} END {print fonduri " RON"}' cont.txt: Calculează soldul pe baza tranzacțiilor din fișier. Variabile utile: ○ NF: numărul de câmpuri din linia curentă. ○ NR: numărul de linii citite până acum. ○ FILENAME: numele fișierului de intrare. Funcții utile: ○ toupper(), tolower(): convertește în majuscule și minuscule. ○ exp(), log(), sin(): funcții matematice. ○ length(): lungimea șirului. ○ int(): partea întreagă a numărului. Mai multe exemple: ○ echo "Ana are mere" | awk '{for(i=1; i