3. Expresii regulate. Filtre. Comanda sed.1. Expresii regulateExpresiile regulate sunt niste siruri de caractere ce reprezinta sabloane sau tipare (pattern in limba engleza). Ele se construiesc pe baza unei gramatici, la fel ca si un limbaj de programare. Aceste sabloane sunt folosite pentru "recunoasterea" si manipularea unor siruri de caractere.
Analog cu expresiile aritmetice, o expresie regulata este construita prin combinarea unor expresii mai mici cu ajutorul unor operatori. a.zAceasta expresie regulata se potriveste cu orice sir de caractere ce contine literele 'a' si 'z' intre care se gaseste orice caracter -- dar unul singur (cu exceptia caracterului newline, deobicei), cum ar fi: "axz", "aaz", "barza", dar nu "abcz". Cele mai simple expresii regulate sunt cele care "se potrivesc" cu un singur caracter: majoritatea caracterelor (toate literele si cifrele) se potrivesc cu ele insele. Alte caractere insa au semnificatie speciala , si daca dorim ca expresia regulata sa se potriveasca cu acel caracter, trebuie sa il citam (quote in limba engleza). Aceasta se poate realiza prin plasarea unui backslash ( '\' ) in fata caracterului respectiv. Expresiile regulate mai complexe se vor forma fie prin concatenare (scriere una dupa alta) fie cu ajutorul operatorilor ce vor fi descrisi mai jos. Prin concatenarea a doua expresii regulate rezulta o expresie regulata ce se va potrivi cu siruri de caractere ce contin doua subsiruri adiacente ce se vor potrivi cu prima respectiv a doua expresie regulata. O alta constructie care potriveste un singur caracter este o lista de caractere inchise intre paranteze drepte. Aceasta expresie se va potrivi cu oricare din caracterele din lista. Astfel, expresia regulata compl[ei]mentse va potrivi cu oricare din sirurile "complement", "compliment" sau "multumesc pentru complimentul dumneavoastra". Daca o constructie cu paranteze drepte incepe cu un ^ , atunci ea se va potrivi cu orice caracter ce nu este intre paranteze: 3[^6890]reprezinta o expresie regulata ce se potriveste cu orice sir ce contine cifra 3 si nu contine pe pozitia urmatoare una din cifrele 6, 8, 9 sau 0 (atentie: daca in sirul caruia i se aplica expresia regulata nu contine dupa 3 nici un alt caracter, expresia nu se va potrivi! ). De asemenea se pot specifica intervale intregi ( considerind ordinea ASCII a caracterelor) cu ajutorul cratimei: [A-Za-z]reprezinta orice litera, mica sau mare. Caracterele care nu se potrivesc cu ele insele si de care aminteam mai sus sunt metacaractere si operatori. O parte dintre ele, printre cele mai des utilizate si implementate in diversele variante de expresii regulate le vom descrie mai jos, alaturi de alte constructii. Punctul (.) se potriveste cu orice caracter, unul singur ( mai putin caracterul newline , de obicei ). Expresiile regulate formate cu caracterele ^ si $ sunt putin mai speciale, ele nu se potrivesc cu un sir de caractere ci cu sirul vid de la inceputul si respectiv sfirsitul unui rind (sir). De exemplu ^turing$se va potrivi doar cu sirul "turing" (nu si cu "featuring" sau "turing "). Sunt definiti o serie de operatori pentru a specifica repetitiile. Ei se aplica in dreapta unei expresii regulate , facand-o sa se potriveasca repetitiv:
Parantezele rotunde se folosesc pentru a grupa expresiile regulate. Astfel, daca scriem ab*aceasta semnifica un 'a' urmat de oricate 'b'-uri (inclusiv nici unul) ; dar daca scriem (ab)*operatorul * se aplica grupului, semnificatia fiind 0 sau mai multe repetitii ale sirului de caractere "ab". Un alt operator util este |, operatorul de alternare. Rezultatul lui este ca se va potrivi fie expresia regulata din stanga, fie cea din dreapta: ion (pozitiv)|(negativ)se va potrivi fie cu "ion pozitiv" fie cu "ion negativ". Pentru mai multe detalii, consultati paginile de manual grep(1) si perlre(1). Ultima prezinta expresiile regulate implementate in limbajul perl, si nu vor fi intotdeauna compatibile cu comenzi precum grep si sed. In schimb gasiti acolo o descriere mai amanuntita. Expresiile regulate pot fi folosite si din limbaje de programare precum C, vedeti regex(3) si regex(7). 2. FiltreFiltrele sunt comenzi care citesc rand cu rand fisierul standard de intrare si afiseaza la iesirea standard parte sau randurile citite, modificate sau nu, functie de semantica lor. Operatia continua pina la intalnirea marcajului de sfarsit de fisier. Aceste comenzi se inlanuie des cu ajutorul pipe-urilor, pentru a le conjuga efectul. In sistemele UNIX exista o serie de comenzi care se comporta ca filtre, multe dintre ele facand parte din standardul POSIX. Majoritatea filtrelor pot insa citi date si din fisiere specificate in linia de comanda. In continuare vom da o scurta descriere pentru cateva filtre mai des folosite:
3. Comanda sedComanda sed deriva din editorul ed care este orientat pe linie (spre deosebire de chiar cele mai simple editoare actuale care sunt orientate pe ecran). Spre deosebire de acesta din urma, sed nu este interactiv ci aplica tuturor sau unui grup de linii din fisierul prelucrat (care poate fi intrarea standard daca nu se specifica un nume de fisier ca parametru) o anumita comanda. Sintaxa (simplificata) este:sed [-n] [-e script] [-f script-file] [script-if-no-other-script] [file...]Optiunile -e (dupa care urmeaza o comanda) si -f (dupa care urmeaza un nume de fisier care contine cate o comanda pe fiecare rand) adauga comenzi in lista celor ce vor fi aplicate asupra liniilor de text. Daca nici -e si nici -f nu sunt gasite, primul parametru care nu este optiune (nu incepe cu cratima) este considerat comanda. Daca dupa ce s-au prelucrat parametrii asa cum am descris mai raman si alti parametri in linia de comanda, acestia se vor considera ca nume de fisiere care trebuie procesate (in care caz sed nu se mai comporta ca filtru). Sintaxa comenzilor sed este destul de complexa. Descrierea completa o gasiti in pagina texinfo a comenzii sed (in pagina de manual descrierea nu este foarte clara) pe care o puteti citi cu comanda info sed. In general o comanda sed este compusa dintr-o adresa sau interval de adrese de linii urmat de un caracter ce reprezinta o actiune de efectuat, urmat eventual de un sir de caractere a carui semnificatie depinde de actiune. Intervalele de adrese se specifica sub forma a doua adrese despartite prin virgula. O adresa poate fi un numar si atunci reprezinta numarul liniei, sau o expresie regulata incadrata de caractere '/', caz in care reprezinta prima linie (incepand cu linia curenta) ce corespunde (se potriveste) expresiei regulate. O adresa mai poate fi si caracterul $, care semnifica "ultima linie a ultimului fisier de intrare". Actiunile corespunzatoare comenzilor nu se vor aplica, in cazul in care avem adrese, decat liniilor corespunzatoare adresei respectiv liniilor cuprinse in intervalul dat. Cea mai des folosita actiune (sau comanda) este cea de substitutie. Ea are forma: s/regexp/replacement/flagsunde regexp este o expresie regulata, replacement este un sir de caractere cu care se va inlocui acea parte a liniei prelucrate care corespunde expresiei regulate, iar flags este o lista de zero sau mai multe caractere dintre urmatoarele:
sed -e 's/^\([^:]*:[^:]*:\)10\([0-9][0-9]\)/\120\2/' /etc/passwdInlocuieste in fisierul de parole id-urile de utilizator cu valori intre 1000 si 1099 cu id-uri cu valori cu 1000 mai mari (intre 2000 si 2099). Daca se foloseste fisierul: gigi:x:500:500::/home/gigi:/bin/bash mimi:x:1000:500::/home/mimi:/bin/bash nini:x:1011:1011::/home/nini:/bin/bash fifi:x:500:1012::/home/fifi:/bin/bash bibi:x:1013:500::/home/bibi:/bin/bashva fi tiparit urmatorul rezultat: gigi:x:500:500::/home/gigi:/bin/bash mimi:x:2000:500::/home/mimi:/bin/bash nini:x:2011:1011::/home/nini:/bin/bash fifi:x:500:1012::/home/fifi:/bin/bash bibi:x:2013:500::/home/bibi:/bin/bashPentru intelegerea expresiei regulate aveti in vedere:
4. Exemple
5. ExercitiiScrieti un shell script care tipareste numarul liniilor dintr-un fisier dat ca parametru care nu sunt comentarii, cat si numarul de caractere punct si virgula (;) care apar in aceste linii. O linie se considera ca fiind comentariu daca incepe cu oricite spatii urmate de semnul diez (#) sau doua slash-uri (//). Daca este invocat fara parametri, script-ul va citi linii de la intrarea standard.Problema:Scrieti un shell script care citeste de la intrarea standard propozitii, cite una pe linie. Scriptul va verifica un set de reguli dat mai jos si de asemenea va afisa propozitia citita, aducindu-i anumite modificari. In cazul in care linia citita nu corespunde setului de reguli enuntat, script-ul va afisa, in locul liniei modificate, mesajul "eroare: <textul citit>".Se vor verifica urmatoarele:
In continuare dam citeva exemple de propozitii
Autor: Petre Mierlutiu |