06. Procesarea textului
În laboratorul 5 ați aflat ce utilizator rulează fiecare program și cine are voie să citească și să scrie fiecare
fișier. În acest laborator lucrați cu ce se află în majoritatea acestor fișiere: text. Faceți cunoștință cu
filtrele, comenzi mici care citesc linii și scriu linii: cat, head, tail și sort lucrează cu linii întregi,
grep găsește liniile care se potrivesc cu o expresie regulată, cut, tr și sed schimbă conținutul fiecărei
linii, iar wc și awk numără și calculează. Le legați apoi în înlănțuiri de comenzi (pipelines) care răspund
la o întrebare într-o singură linie, aflați din codul de ieșire dacă o comandă a reușit și legați comenzi între ele
cu && și ||. La final, editați fișiere text în terminal cu nano și vim și încercați un editor mai nou, Helix (hx).
Ideea cea mai importantă a laboratorului este că textul este limba comună a comenzilor. Fiecare filtru citește linii de text, face un singur lucru mic cu ele și scrie linii de text, așa că ieșirea oricărui filtru poate fi intrarea oricărui alt filtru. Pipe-urile leagă filtrele într-o înlănțuire: fiecare comandă îi dă textul celei următoare, cu un pas mai aproape de răspuns, iar ultima îl afișează. Pe lângă text, fiecare comandă întoarce și un număr, codul de ieșire, prin care îi spune shell-ului dacă a reușit.
Obiective
- Să înțelegeți ce este un filtru și să construiți o înlănțuire de filtre care răspunde la o întrebare
- Să afișați, să inversați și să decupați linii cu
cat,tac,headșitail - Să sortați linii cu
sort, ca text, ca numere și după un câmp, și să numărați liniile repetate cuuniq - Să scrieți expresii regulate, de bază și extinse, și să căutați cu ele folosind
grep - Să extrageți câmpuri și caractere din fiecare linie cu
cutși să inversați sau să numerotați liniile curevșinl - Să schimbați, să ștergeți și să comprimați caractere cu
trși să înlocuiți text cused - Să numărați liniile, cuvintele și caracterele cu
wcși să calculați sume și medii cuawk - Să aflați din codul de ieșire dacă o comandă a reușit și să legați comenzi cu
&&și|| - Să editați un fișier text în terminal cu
nanoși cuvimși să încercațihx
Resurse
- Razvan Deaconescu, Razvan Rughinis, Mihai Carabas, Alexandru Radovici, Utilizarea Sistemelor de
Operare, Printech 2021
- Capitolul 4 - Procese, secțiunile 4.5.3 și 4.5.4
- Capitolul 6 - Dezvoltarea aplicațiilor, secțiunile 6.6.1 și 6.6.2
- Capitolul 7 - Interfața în linia de comandă, secțiunile 7.4 și 7.5
- Capitolul 13 - Automatizarea sarcinilor, secțiunea 13.3.2
- Brian Ward, How LINUX Works, 3rd Edition, No Starch Press, 2021
- Capitolul 2 - Basic Commands and Directory Hierarchy, secțiunile 2.2.2, 2.5 și 2.14
- Capitolul 11 - Introduction to Shell Scripts, secțiunile 11.4 și 11.5
- The GNU Awk User's Guide și
vimtutor, tutorialul de 30 de minute al luivim - Slide-urile cursului: 06. Procesarea textului
- Paginile de manual:
man cat,man tac,man head,man tail,man sort,man uniq,man grep,man 7 regex,man cut,man tr,man sed,man rev,man nl,man wc,man awk,man nano,man vimșiman bash(căutațiPipelinesșiLists)
Fedora și Ubuntu
Calculatoarele din laborator rulează Fedora cu Sway, iar exemplele de aici provin de pe ele. Acasă puteți folosi și Ubuntu: comenzile din acest laborator sunt aceleași, cu câteva diferențe:
| Fedora | Ubuntu | |
|---|---|---|
| promptul | [student@fedora ~]$ | student@ubuntu:~$ |
programul din spatele lui awk | GNU awk (gawk) | mawk, un awk mai mic: laboratorul merge la fel și cu el |
vim și vimtutor | dacă lipsesc: sudo dnf install vim-enhanced | dacă lipsesc: sudo apt install vim |
instalarea Helix (hx) | sudo dnf install helix | sudo snap install --classic helix |
Filtre
Un filtru este o comandă care citește text, face o singură treabă cu el și scrie rezultatul la ieșirea
standard. Citește fișierele primite ca parametri sau, dacă nu primește niciunul, intrarea standard. În secțiunea
Pipe-uri din laboratorul 3 ați legat deja câteva filtre cu |: sort fruits.txt | uniq -c.
Un șir de comenzi legate prin pipe-uri formează o înlănțuire.
Gândiți-vă la o bandă de montaj dintr-o fabrică: fiecare muncitor face o singură operație mică pe piesă și o dă mai departe. La fel, un filtru nu știe ce se află înaintea lui sau după el: cunoaște doar intrarea și ieșirea lui.
Filtrele din acest laborator fac patru feluri de treburi, iar o înlănțuire tipică le folosește în ordinea aceasta:
| Tip | Ce face | Comenzi |
|---|---|---|
| filtre de linii | alege ce linii păstrează și în ce ordine | cat, tac, head, tail, sort, uniq |
| căutare | păstrează liniile care se potrivesc cu un tipar | grep |
| modificarea textului | schimbă conținutul fiecărei linii | cut, tr, sed, rev, nl |
| calcul | transformă liniile într-un număr, o sumă, ... | wc, uniq -c, awk |
Ce adrese au cerut pagini care nu există, și de câte ori? Răspunsul încape într-o singură linie:
[student@fedora lab06]$ grep ' 404$' access.log | cut -d' ' -f1 | sort | uniq -c
2 10.0.0.3
3 10.0.0.9
grepa păstrat liniile care se termină cu404, adică cererile pentru pagini inexistente;cuta păstrat doar primul câmp, adresa;sort | uniq -ca numărat fiecare adresă. Secțiunile următoare explică pe rând fiecare comandă.
Construiți o înlănțuire comandă cu comandă
Rulați prima comandă și uitați-vă la rezultat. Apoi apăsați ↑, adăugați | și comanda următoare și uitați-vă
din nou: fiecare pas ar trebui să aducă textul puțin mai aproape de răspuns. Cât timp lucrați, puneți | head la final
ca să vedeți doar primele linii dintr-un rezultat lung, apoi scoateți-l când ați terminat.
„Scrieți programe care fac un singur lucru și îl fac bine. Scrieți programe care să lucreze împreună. Scrieți programe care prelucrează fluxuri de text, pentru că textul este o interfață universală.” (Doug McIlroy, cel care a inventat pipe-ul în Unix)
Toate comenzile unei înlănțuiri rulează în același timp, fiecare în propriul proces, iar textul curge între ele cât timp rulează. Exercițiile de acasă și provocările au nevoie de detalii: le găsiți în Cum rulează o înlănțuire.
Filtre de linii
Filtrele de linii lucrează cu linii întregi: aleg ce linii păstrează și în ce ordine, dar nu le modifică. Exemplele
folosesc fișierele pe care le creează exercițiul 2 în ~/lab06; fruits.txt are 7 linii:
banana, apple, cherry, apple, kiwi, banana și apple.
Afișarea unui fișier: cat și tac
Ați întâlnit cat în laboratorul 2. Opțiunile lui scot la iveală ce nu se vede în text:
| Comandă | Ce face |
|---|---|
cat <FILE>... | afișează fișierele, unul după altul (concatenate) |
cat | fără niciun fișier, afișează ce citește de la tastatură, până la Ctrl+D |
cat -n <FILE> | numerotează fiecare linie |
cat -A <FILE> | arată caracterele invizibile: un tab ca ^I, sfârșitul fiecărei linii ca $ |
tac <FILE> | afișează liniile în ordine inversă, întâi pe ultima |
[student@fedora lab06]$ tac fruits.txt
apple
banana
kiwi
apple
cherry
apple
banana
[student@fedora lab06]$ printf 'a\tb \n' | cat -A
a^Ib $
taca afișat aceleași 7 linii, de la ultima la prima.cat -Aa scos la iveală tab-ul dintreașibși spațiul de la sfârșitul liniei, dinaintea lui$.
Primele și ultimele linii: head și tail
| Comandă | Ce afișează |
|---|---|
head -n <N> <FILE> | primele N linii; fără -n, primele 10 |
head -n -<N> <FILE> | toate liniile, mai puțin ultimele N |
tail -n <N> <FILE> | ultimele N linii; fără -n, ultimele 10 |
tail -n +<N> <FILE> | liniile începând cu linia N, până la final: -n +2 sare doar peste prima linie |
tail -f <FILE> | ultimele linii, apoi fiecare linie nouă scrisă în fișier, până la Ctrl+C (follow) |
[student@fedora lab06]$ head -n 3 fruits.txt
banana
apple
cherry
[student@fedora lab06]$ head -n 5 fruits.txt | tail -n 1
kiwi
[student@fedora lab06]$ tail -n +2 students.csv
Alice,30,Paris
Bob,25,London
Carol,22,Bucharest
head -n 5 | tail -n 1a păstrat primele 5 linii, apoi ultima dintre ele: linia a 5-a.tail -n +2a sărit peste prima linie dinstudents.csv, antetul cu numele coloanelor.
Cu tail -f urmăresc administratorii un jurnal (log), un fișier în care un program adaugă câte o linie pentru tot
ce face. Lăsați comanda să ruleze într-un terminal și vedeți fiecare linie nouă în clipa în care apare.
Sortarea: sort
sort afișează liniile în ordine alfabetică. Opțiunile schimbă ce anume compară:
| Opțiune | Ce face |
|---|---|
-r | sortează în ordine inversă |
-n | compară liniile ca numere: 9 înainte de 10 |
-u | afișează fiecare linie o singură dată (unique) |
-t <C> | câmpurile sunt separate de caracterul C (implicit: spații) |
-k <N>,<N> | sortează doar după câmpul N; -k 2,2n: după câmpul 2, ca număr; -k 2: de la câmpul 2 până la final |
Sortăm numbers.txt ca text, apoi ca numere, iar la final students.csv după vârstă:
[student@fedora lab06]$ sort numbers.txt
10
100
2
9
[student@fedora lab06]$ sort -n numbers.txt
2
9
10
100
[student@fedora lab06]$ sort -t, -k 2,2n students.csv
name,age,city
Carol,22,Bucharest
Bob,25,London
Alice,30,Paris
- Fără
-n,sorta comparat numerele ca text, caracter cu caracter:100a ieșit înaintea lui2, pentru că1vine înaintea lui2. -t, -k 2,2na sortat liniile dinstudents.csvdupă al doilea câmp, vârsta, ca număr. Antetul nu are un număr în acest câmp, așa că valorează0și rămâne primul.
Fără -n, numerele se sortează ca text: 100 înainte de 2. Folosiți -n ori de câte ori liniile încep cu un
număr, sau -k cu n când numărul se află în alt câmp.
Numărarea liniilor repetate: uniq
Ați întâlnit uniq în Linii repetate din laboratorul 3: compară o linie doar cu
linia imediat de deasupra, de aceea vine după sort. Împreună cu sort -nr și head, găsește liniile cele mai
frecvente:
[student@fedora lab06]$ sort fruits.txt | uniq -c | sort -nr | head -n 2
3 apple
2 banana
sort | uniq -ca numărat fiecare fruct,sort -nra pus primul cel mai mare număr, iarhead -n 2a păstrat primele două.
| Opțiune | Ce afișează |
|---|---|
uniq -c | fiecare linie o singură dată, cu numărul de apariții |
uniq -d | doar liniile care apar de mai multe ori |
uniq -u | doar liniile care apar exact o dată |
Expresii regulate
O expresie regulată (regular expression, pe scurt regex) este un tipar care descrie un text. De exemplu, c.l
înseamnă „un c, apoi orice caracter, apoi un l”: se potrivește cu col din color și cu cal din call.
Majoritatea programelor care caută în text înțeleg expresii regulate: grep, sed și awk, căutarea cu /
din less, man și vim și aproape orice limbaj de programare.
Gândiți-vă cum descrieți o persoană unui prieten care o așteaptă la gară: nu știți cum se numește, dar „înaltă, cu o pălărie roșie” îl ajută să o găsească în mulțime. La fel, un regex găsește liniile care se potrivesc cu descrierea.
grep '<REGEX>' <FILE> afișează liniile care conțin o potrivire a regex-ului. Exemplele folosesc words.txt:
color
colour
cat
category
concatenate
dog
banana
bat
orange
gal
goal
gooooal
notes.txt
2026-10-04
call 0722 123 456
Un regex nu este un glob
Într-un glob (vedeți Globbing din laboratorul 4), * înseamnă „orice caractere”; într-un
regex, * înseamnă „elementul anterior, de oricâte ori”, iar „orice caractere” se scrie .*. Puneți întotdeauna
regex-ul între ghilimele simple: altfel, shell-ul îl poate expanda ca pe un glob, înainte să pornească grep. Dacă
în directorul curent există un fișier banana.txt, grep ba* fruits.txt devine grep banana.txt fruits.txt.
Expresii regulate de bază
| Regex | Înseamnă | Exemplu | Liniile din words.txt care se potrivesc |
|---|---|---|---|
abc | textul abc, oriunde în linie | cat | cat, category, concatenate |
. | orice caracter, unul singur | c.l | color, colour, call ... |
^ | începutul liniei | ^ca | cat, category, call ... |
$ | sfârșitul liniei | r$ | color, colour |
[abc] | unul dintre caracterele dintre paranteze (o clasă) | [0-9] | 2026-10-04, call ... |
[^abc] | un caracter care nu se află între paranteze; ^ înseamnă nu doar imediat după [ | ^[^c] | orice linie care nu începe cu c |
* | elementul anterior, de 0 sau mai multe ori | go*al | gal, goal, gooooal |
.* | orice caractere, sau niciunul | ^c.*e$ | concatenate |
\ | următorul caracter este text obișnuit: \. este un punct adevărat | \. | notes.txt |
Să le vedem în acțiune pe câteva dintre ele:
[student@fedora lab06]$ grep 'go*al' words.txt
gal
goal
gooooal
[student@fedora lab06]$ grep '^[a-z]*$' words.txt | wc -l
12
[student@fedora lab06]$ grep '.' words.txt | wc -l
15
[student@fedora lab06]$ grep '\.' words.txt
notes.txt
go*als-a potrivit cu ung, urmat de oricâțio, chiar și de niciunul, apoi deal.^[a-z]*$s-a potrivit cu liniile care au doar litere mici, de la început până la sfârșit: 12 linii..singur s-a potrivit cu orice linie care nu e goală;\.s-a potrivit doar cu linia care conține un punct adevărat.
Expresii regulate extinse
Cu grep -E devin speciale încă cinci caractere: +, ?, { }, ( ) și |, care scurtează regex-ul. Tabelul
arată și \b, pe care GNU grep îl înțelege cu sau fără -E:
| Regex | Înseamnă | Exemplu | Liniile din words.txt care se potrivesc |
|---|---|---|---|
+ | elementul anterior, de 1 sau mai multe ori | [0-9]+ | 2026-10-04, call ... |
? | elementul anterior, de 0 sau 1 dată: este opțional | colou?r | color, colour |
{n} | elementul anterior, de exact n ori; {n,m}: între n și m ori | [0-9]{4} | 2026-10-04, call 0722 ... |
( ) | un grup, repetat ca un singur element | b(an)*a | banana, bat |
| | una dintre alternative (sau) | cat|dog | cat, category, concatenate, dog |
\b | o margine de cuvânt: începutul sau sfârșitul unui cuvânt | \bcat\b | doar cat |
[student@fedora lab06]$ grep -E 'colou?r' words.txt
color
colour
[student@fedora lab06]$ grep -E '^[0-9]{4}-[0-9]{2}-[0-9]{2}$' words.txt
2026-10-04
[student@fedora lab06]$ grep -E '\b[0-9]{3}\b' words.txt
call 0722 123 456
^[0-9]{4}-[0-9]{2}-[0-9]{2}$s-a potrivit cu o linie care conține doar o dată calendaristică: 4 cifre,-, 2 cifre,-, 2 cifre.\b[0-9]{3}\bs-a potrivit cu un număr de exact 3 cifre,123; fără\b, s-ar fi potrivit și în interiorul lui0722și al lui2026.
Fără -E, grep folosește expresiile regulate de bază, în care +, ?, {, ( și | sunt caractere obișnuite
(speciale sunt, în schimb, \+, \?, ...). Folosiți -E ori de câte ori aveți nevoie de unul dintre ele. Lista
completă se află în man 7 regex.
Opțiunile lui grep
| Opțiune | Ce face |
|---|---|
-E | folosește expresiile regulate extinse |
-i | nu ține cont de majuscule și minuscule |
-v | afișează liniile care nu se potrivesc |
-n | afișează numărul fiecărei linii în fața ei |
-c | afișează doar numărul de linii care se potrivesc; o linie cu două potriviri se numără o dată |
-o | afișează doar partea care se potrivește, fiecare potrivire pe linia ei |
-w | se potrivește doar cu cuvinte întregi, ca și cum regex-ul ar fi încadrat de \b...\b |
-q | nu afișează nimic (quiet): răspunsul se află în codul de ieșire (vedeți Coduri de ieșire) |
-r | caută în toate fișierele dintr-un director și din subdirectoarele lui |
[student@fedora lab06]$ grep -n 'an' fruits.txt
1:banana
6:banana
[student@fedora lab06]$ grep -o -E '[0-9]+' words.txt
2026
10
04
0722
123
456
[student@fedora lab06]$ grep -v -c 'apple' fruits.txt
4
-na arătat căbananase află pe liniile1și6.-oa afișat fiecare număr dinwords.txtpe linia lui, fără restul liniei.-v -ca numărat liniile care nu conținapple.
Modificarea textului
Câmpuri și delimitatori
Multe fișiere text sunt de fapt tabele: fiecare linie este un rând, iar un caracter, delimitatorul, o împarte în
câmpuri, adică în coloane. Câmpurile se numerotează de la 1.
| Fișier | O linie | Delimitatorul |
|---|---|---|
| un fișier CSV (comma-separated values) | Alice,30,Paris | , |
/etc/passwd (laboratorul 5) | student:x:1000:1000:Student:/home/student:/bin/bash | : |
un fișier jurnal, access.log | 10.0.0.9 GET /logo.png 404 | un spațiu |
| multe programe | câmpurile sunt aliniate în coloane | un tab |
Fiecare delimitator desparte. În Bob 25 London, cu trei spații după Bob, între spații există două câmpuri
goale, iar 25 este câmpul 4, nu 2.
Extragerea coloanelor: cut
| Comandă | Ce afișează |
|---|---|
cut -d<C> -f<N> <FILE> | câmpul N al fiecărei linii; câmpurile sunt separate de caracterul C |
cut -d<C> -f1,3 | câmpurile 1 și 3, separate de același C, în ordinea din linie: și -f3,1 afișează întâi câmpul 1 |
cut -d<C> -f2-4, -f2- | câmpurile de la 2 la 4; de la câmpul 2 până la final |
cut -f<N> | fără -d, delimitatorul este tab-ul; o linie fără niciun tab se afișează întreagă, oricare ar fi N |
cut -c<N>-<M> <FILE> | caracterele de la N la M ale fiecărei linii, numărate de la 1 |
[student@fedora lab06]$ cut -d, -f1 students.csv
name
Alice
Bob
Carol
[student@fedora lab06]$ cut -d, -f2- students.csv
age,city
30,Paris
25,London
22,Bucharest
[student@fedora lab06]$ cut -d' ' -f2 people.txt
30
-d, -f1a afișat primul câmp, numele;-f2-a afișat tot ce urmează, începând cu al doilea câmp.people.txtconțineAlice 30 ParisșiBob 25 London: pentruBob, câmpul2este câmpul gol dintre primele două spații, așa căcuta afișat o linie goală.tr, din secțiunea următoare, rezolvă problema.
Schimbarea caracterelor: tr
tr (translate) schimbă caractere individuale, nu cuvinte. Citește doar de la intrarea standard: dați-i
fișierul cu < sau printr-un pipe.
| Comandă | Ce face | Exemplu |
|---|---|---|
tr <SET1> <SET2> | transformă fiecare caracter din SET1 în caracterul aflat pe aceeași poziție în SET2 | tr abc xyz: cab → zxy |
tr -d <SET> | șterge fiecare caracter din SET | tr -d a: banana → bnn |
tr -s <SET> | comprimă o secvență din același caracter din SET într-unul singur | tr -s o: gooooal → goal |
Un set este o listă de caractere, aeiou, sau un interval, a-z, 0-9; '\n' este sfârșitul de linie, iar '\t'
un tab.
[student@fedora lab06]$ tr a-z A-Z < fruits.txt | head -n 2
BANANA
APPLE
[student@fedora lab06]$ echo 'call 0722 123 456' | tr -d 0-9
call
[student@fedora lab06]$ tr -s ' ' < people.txt | cut -d' ' -f2
30
25
[student@fedora lab06]$ echo "$PATH" | tr : '\n'
/home/student/.local/bin
/home/student/bin
/usr/local/bin
/usr/bin
...
a-zșiA-Zau aceeași lungime:aa devenitA,ba devenitBși așa mai departe.-d 0-9a șters cifrele; spațiile au rămas.tr -s ' 'a lăsat un singur spațiu între câmpurile dinpeople.txt, așa căcuta găsit vârsta luiBobîn câmpul2.tr : '\n'a pus fiecare director dinPATH(laboratorul 4) pe linia lui.
Înlocuirea textului: sed
sed (stream editor) modifică textul pe măsură ce trece prin el, ca un muncitor la banda de montaj: citește o linie,
o modifică, o afișează și trece la următoarea. Fișierul în sine nu se schimbă. Spre deosebire de tr, sed lucrează
cu cuvinte și cu expresii regulate, nu cu caractere individuale. Comanda lui cea mai folosită este s (substitute),
care înlocuiește textul cu care se potrivește un regex:
sed 's/<REGEX>/<NEW TEXT>/<FLAGS>' <FILE>
| Se scrie | Ce face |
|---|---|
s/apple/pear/ | înlocuiește prima potrivire din fiecare linie |
s/apple/pear/g | înlocuiește toate potrivirile din linie (global) |
s/apple/pear/gi | la fel, fără să țină cont de majuscule și minuscule |
sed -E 's/...//' | regex-ul este unul extins, ca la grep -E |
s/apple//g | textul nou este gol: șterge potrivirile |
s|/usr|/opt| | părțile pot fi separate de orice caracter: util când textul conține / |
[student@fedora lab06]$ echo 'apple and apple pie' | sed 's/apple/pear/'
pear and apple pie
[student@fedora lab06]$ echo 'apple and apple pie' | sed 's/apple/pear/g'
pear and pear pie
[student@fedora lab06]$ echo 'call 0722 123 456' | sed -E 's/[0-9]+/N/g'
call N N N
[student@fedora lab06]$ sed 's/,/ /g' students.csv
name age city
Alice 30 Paris
Bob 25 London
Carol 22 Bucharest
- Fără
g, s-a schimbat doar primulapple. [0-9]+s-a potrivit cu fiecare număr, iar fiecare potrivire a devenitN.seda afișat textul modificat;students.csvîn sine nu s-a schimbat.
sed -i scrie rezultatul înapoi în fișier, în loc să-l afișeze, și nu există undo. Rulați întâi comanda fără -i
și uitați-vă la rezultat.
Inversarea și numerotarea: rev și nl
| Comandă | Ce face |
|---|---|
rev <FILE> | inversează caracterele fiecărei linii; ordinea liniilor rămâne aceeași (pe aceea o inversează tac) |
nl <FILE> | adaugă o primă coloană cu numărul liniei, urmat de un tab; liniile goale nu primesc număr |
[student@fedora lab06]$ rev fruits.txt | head -n 2
ananab
elppa
[student@fedora lab06]$ echo /usr/share/doc/bash | rev | cut -d/ -f1 | rev
bash
cutnu poate număra câmpurile de la sfârșit.reva adus ultimul câmp pe primul loc,cut -f1l-a luat, iar al doilearevl-a întors la loc.
Numărare și calcul
Numărarea: wc
wc (word count) numără liniile, cuvintele și octeții:
| Opțiune | Ce numără |
|---|---|
-l | liniile |
-w | cuvintele: grupurile de caractere separate prin spații |
-c | octeții |
-m | caracterele: o literă ca ș ocupă 2 octeți, dar este un singur caracter |
[student@fedora lab06]$ wc fruits.txt
7 7 44 fruits.txt
[student@fedora lab06]$ wc -l < fruits.txt
7
[student@fedora lab06]$ echo 'mașină' | wc -c -m
7 9
- Fără opțiuni,
wca afișat liniile, cuvintele și octeții, apoi numele fișierului. - Cu
<,wcnu a aflat numele fișierului (vedeți Intrarea din laboratorul 3), așa că a afișat doar numărul. mașinăîmpreună cu sfârșitul de linie înseamnă 7 caractere, dar 9 octeți:șșiăocupă câte doi octeți.
Calculul: awk
awk este un mic limbaj de programare pentru tabele. Un program awk este o listă de condiții, fiecare cu o
acțiune între { }: awk împarte fiecare linie în câmpuri și rulează acțiunea fiecărei condiții adevărate pentru
linia respectivă. Condiția este opțională; END este o condiție adevărată o singură dată, după ultima linie.
| Se scrie | Ce este |
|---|---|
-F, | delimitatorul este ,; fără -F, orice secvență de spații și tab-uri |
$1, $2, ..., $NF | câmpurile; $NF este ultimul câmp, a nu se confunda cu NF; $0 este linia întreagă |
NF, NR | numărul de câmpuri din linie; numărul liniei, de la 1 |
==, !=, <, >=, ... | compară două valori: numerele ca numere, textul ca text; textul se pune între ": $2 == "apple" |
~ /regex/, !~ /regex/ | se potrivește, nu se potrivește cu un regex |
&&, ||, ! | și, sau, nu |
{ print $1, $3 } | afișează câmpurile 1 și 3, separate printr-un spațiu; print $1 $3, fără ,, afișează alice3 |
{ s += $3; n++ } | adună câmpul 3 la variabila s și adună 1 la n; variabilele pornesc de la 0 |
Exemplele folosesc orders.csv, un antet urmat de 6 comenzi de fructe:
name,fruit,count
alice,apple,3
bob,kiwi,1
carol,apple,2
alice,banana,5
dan,apple,1
alice,apple,2
[student@fedora lab06]$ awk -F, '{ s += $3 } END { print s }' orders.csv
14
[student@fedora lab06]$ awk -F, 'NR > 1 { s += $3; n++ } END { print s / n }' orders.csv
2.33333
[student@fedora lab06]$ awk -F, '$2 == "apple" { s += $3 } END { print s }' orders.csv
8
[student@fedora lab06]$ awk -F, '$2 ~ /an/ { print $1, $2 }' orders.csv
alice banana
[student@fedora lab06]$ awk '{ print NF, $NF }' people.txt
3 Paris
3 London
- Primul program a adunat câmpul 3 al fiecărei linii și a afișat suma la final; antetul
countnu este un număr, așa că a adunat0. NR > 1a sărit peste antet, iarna numărat comenzile: 14 / 6 = 2.33333.$2 == "apple"a adunat doar merele;$2 ~ /an/a afișat comenzile al căror fruct conținean.- Fără
-F,awka despărțitBob 25 Londonla secvența de spații: 3 câmpuri, niciunul gol.
Puneți programul awk între ghilimele simple: $1 și $3 sunt pentru awk, nu pentru shell.
O înlănțuire, pas cu pas
Câți clienți au comandat mere? Construim înlănțuirea comandă cu comandă și ne uităm la text după fiecare pas:
[student@fedora lab06]$ tail -n +2 orders.csv | grep ',apple,'
alice,apple,3
carol,apple,2
dan,apple,1
alice,apple,2
[student@fedora lab06]$ tail -n +2 orders.csv | grep ',apple,' | cut -d, -f1
alice
carol
dan
alice
[student@fedora lab06]$ tail -n +2 orders.csv | grep ',apple,' | cut -d, -f1 | sort -u
alice
carol
dan
[student@fedora lab06]$ tail -n +2 orders.csv | grep ',apple,' | cut -d, -f1 | sort -u | wc -l
3
tail -n +2a sărit peste antet, iargrep ',apple,'a păstrat comenzile de mere; virgulele din jurul luiapplelasă deoparte un fruct capineapple.cuta păstrat numele;alicea comandat mere de două ori, așa căsort -ua păstrat fiecare nume o singură dată;wc -lle-a numărat.
Coduri de ieșire
Fiecare comandă se termină cu un număr între 0 și 255, codul de ieșire: 0 înseamnă succes, orice alt
număr înseamnă o eroare. Shell-ul păstrează codul de ieșire al ultimei comenzi în $? (vedeți
Parametri speciali din laboratorul 4). Ce înseamnă fiecare număr aflați din
pagina de manual a comenzii, în secțiunea EXIT STATUS:
grep se termină cu | Când |
|---|---|
0 | a găsit cel puțin o linie |
1 | nu a găsit nimic |
2 | a apărut o eroare: de exemplu, fișierul nu există |
[student@fedora lab06]$ grep -q kiwi fruits.txt
[student@fedora lab06]$ echo $?
0
[student@fedora lab06]$ grep -q mango fruits.txt
[student@fedora lab06]$ echo $?
1
[student@fedora lab06]$ grep kiwi nope.txt
grep: nope.txt: No such file or directory
[student@fedora lab06]$ echo $?
2
grep -qnu a afișat nimic; codul de ieșire a spus dacă a găsitkiwi(0) sau nu (1).
| Comandă | Ce face |
|---|---|
true | nimic; se termină cu 0 |
false | nimic; se termină cu 1 |
exit <N> | încheie shell-ul, sau un script, cu codul de ieșire N |
O comandă omorâtă de un semnal (laboratorul 4) se termină cu 128 plus numărul semnalului: Ctrl+C
(SIGINT, 2) dă 130.
Legarea comenzilor: && și ||
| Se scrie | Ce face |
|---|---|
a ; b | rulează a, apoi b, indiferent dacă a a reușit sau nu; ca pe două linii separate |
a && b | rulează b doar dacă a s-a terminat cu 0: „a, și apoi b” |
a || b | rulează b doar dacă a nu s-a terminat cu 0: „a, altfel b” |
[student@fedora lab06]$ grep -q kiwi fruits.txt && echo 'kiwi found'
kiwi found
[student@fedora lab06]$ grep -q mango fruits.txt && echo 'mango found'
[student@fedora lab06]$ grep -q mango fruits.txt || echo 'no mango'
no mango
[student@fedora lab06]$ mkdir -p backup && cp fruits.txt backup/ && echo 'saved'
saved
&&a sărit pesteecho 'mango found', pentru căgreps-a terminat cu1; din același motiv,||a rulatecho 'no mango'.cpa rulat doar după ce a reușitmkdir, iarechodoar după ce a reușitcp.
a && b || c nu înseamnă „dacă a, atunci b, altfel c”. Shell-ul citește de la stânga la dreapta, iar || se
uită la codul de ieșire al ultimei comenzi rulate înaintea lui: când a reușește, aceea este b. Așadar c rulează și
când a reușește, dar b eșuează: true && false || echo C afișează C. Puteți folosi a && b || c ca „dacă a,
atunci b, altfel c” doar când b nu poate eșua, cum e echo: atunci c rulează doar când eșuează a.
Codul de ieșire al unei înlănțuiri
Codul de ieșire al unei înlănțuiri este codul de ieșire al ultimei comenzi:
[student@fedora lab06]$ cut -d, -f2 orders.csv | grep -q kiwi && echo 'kiwi ordered' || echo 'no kiwi'
kiwi ordered
[student@fedora lab06]$ cut -d, -f2 nope.csv | sort
cut: nope.csv: No such file or directory
[student@fedora lab06]$ echo $?
0
- Pe prima linie,
grep -qa găsitkiwiîn coloana fructelor: înlănțuirea s-a terminat cu0. - Pe a doua,
cuta eșuat, darsort, ultima comandă, a reușit: înlănțuirea s-a terminat cu0. Mesajul de eroare apare pe ecran, dar$?,&&și||văd doar0-ul. Cum rulează o înlănțuire arată cum puteți prinde eșecul.
Editoare de text
Editați fișiere text tot timpul: setări în /etc și în ~/.config, programe, notițe. Pe un server, prin rețea, sau
într-un terminal virtual (laboratorul 4) nu aveți nicio fereastră: aveți nevoie de un editor care rulează în
terminal.
| Editor | Cum este |
|---|---|
nano | simplu: ce tastați ajunge în text, iar partea de jos a ecranului listează tastele; este editorul implicit pe Fedora și Ubuntu |
vi, vim, nvim | modal: tastele sunt comenzi, iar textul se scrie doar în modul Insert; vi există pe orice sistem Unix, nvim este un vim mai nou |
emacs | nemodal: fiecare comandă este o combinație cu Ctrl sau Alt; poate fi extins cu programe scrise în limbajul lui |
helix (hx) | modal ca vim, dar întâi selectați și abia apoi acționați; cunoaște limbajele de programare fără nicio setare |
nano
Ați întâlnit nano în laboratorul 2. Partea de jos a ecranului îi listează tastele: ^ înseamnă
Ctrl, iar M- înseamnă Alt.
| Tastă | Acțiune |
|---|---|
| Ctrl+O | salvare (write out), apoi Enter ca să păstrați numele |
| Ctrl+X | ieșire; dacă fișierul s-a schimbat, vă întreabă dacă îl salvați: Y sau N |
| Ctrl+K | taie linia |
| Ctrl+U | lipește liniile tăiate |
| Alt+U | undo |
| Ctrl+W | căutare (where is) |
| Ctrl+\ | căutare și înlocuire |
| Ctrl+_ | salt la o linie, după numărul ei |
vim
vim (Vi IMproved) este modal: aceeași tastă face lucruri diferite în moduri diferite. Pornește în modul
Normal, în care fiecare tastă este o comandă: j nu scrie un j, ci mută cursorul în jos, iar
x șterge un caracter. Ca să scrieți text, apăsați i și intrați în modul Insert; cu
Esc reveniți în modul Normal. Durează puțin până vă obișnuiți, dar tocmai aici stă puterea lui vim: când
editați, petreceți cea mai mare parte a timpului mutându-vă prin text și modificându-l, nu tastându-l, iar în modul
Normal fiecare literă este o comandă, fără vreun Ctrl de ținut apăsat.
| Mod | Ce fac tastele | Intrați în el cu | Pe ultima linie apare |
|---|---|---|---|
| Normal | mută cursorul, șterg, copiază, lipesc | Esc, din orice alt mod | nimic |
| Insert | scriu text | din Normal: i, a, o | -- INSERT -- |
| Linie de comandă | scrieți o comandă: salvare, ieșire, înlocuire; Enter o rulează | : (sau / pentru căutare) | : (sau /) și ce tastați |
| Visual | selectați text, apoi acționați asupra lui: d îl șterge, y îl copiază | v (caractere), V (linii) | -- VISUAL --, -- VISUAL LINE -- |
| În modul Normal | Acțiune |
|---|---|
| h j k l, sau săgețile | stânga, jos, sus, dreapta |
| w, b | cuvântul următor, cuvântul anterior |
| 0, $ | începutul, sfârșitul liniei |
| gg, G | prima linie, ultima linie |
| i, a | modul Insert, înainte, după cursor |
| o, O | o linie nouă dedesubt, deasupra, în modul Insert |
| x, dd | șterge un caracter, șterge (taie) linia: p o lipește înapoi |
| yy, p | copiază (yank) linia, o lipește dedesubt |
| u, Ctrl+R | undo, redo |
/text, n | caută înainte, sare la următoarea potrivire |
:w, :q, :wq, :q! | salvare, ieșire, salvare și ieșire, ieșire fără salvare |
:%s/old/new/g | înlocuire în toate liniile, ca la sed: old este un regex, iar % înseamnă toate liniile |
Un număr pus înaintea unei comenzi o repetă: 5j coboară 5 linii, 3dd șterge 3 linii. Tastele h j k l sunt aceleași ca în Sway, din laboratorul 1.
V-ați rătăcit în vim?
Uitați-vă la ultima linie ca să aflați în ce mod sunteți. Apăsați Esc de câteva ori ca să reveniți în modul
Normal, apoi tastați :q! și Enter ca să ieșiți fără să salvați. Restul vi-l predă vimtutor în 30 de minute.
Cum rulează o înlănțuire
Mai în profunzime
Nu aveți nevoie de această secțiune pentru exercițiile din laborator, 🧪 Primii pași. Citiți-o acasă: o folosesc exercițiile 🏠 Mai departe și 📝 Provocările.
La o înlănțuire, shell-ul pornește toate comenzile în același timp, fiecare ca proces copil, și le leagă prin
pipe-uri. Un pipe este o mică zonă tampon (buffer) din kernel: ieșirea (1) unei comenzi scrie în ea, iar
intrarea (0) comenzii următoare citește din ea. Gândiți-vă la un tub între doi muncitori: primul aruncă piese la un
capăt, al doilea le scoate la celălalt.
| Ce se întâmplă | Rezultatul |
|---|---|
| pipe-ul este gol, iar comanda următoare vrea să citească | aceasta așteaptă până apare text |
| pipe-ul este plin (64 KiB) | comanda care scrie așteaptă până când cea care citește scoate o parte din text |
| comanda care scrie se termină | cea care citește primește end of file (sfârșitul fișierului) și poate termina |
| comanda care citește se termină înaintea celei care scrie | la următoarea scriere, cea care scrie primește semnalul SIGPIPE (13) și se termină |
| Ctrl+C, Ctrl+Z | ajung la toate comenzile: înlănțuirea este un singur job (laboratorul 4) |
[student@fedora lab06]$ yes | head -n 3
y
y
y
[student@fedora lab06]$ echo "${PIPESTATUS[@]}"
141 0
yesafișeazăyla nesfârșit;heads-a terminat după 3 linii, iaryesa primitSIGPIPEla următoarea scriere:128 + 13 = 141.PIPESTATUSeste o variabilă a luibashcare conține codurile de ieșire ale tuturor comenzilor din ultima înlănțuire;$?îl conține doar pe ultimul.
Pipe-urile unui proces se văd în directorul lui din /proc (vedeți
Sistemul de fișiere /proc din laboratorul 3): readlink /proc/<PID>/fd/1
afișează pipe:[48211] când ieșirea 1 merge într-un pipe; ambele capete ale aceluiași pipe au același număr.
| Setare | Ce face |
|---|---|
set -o pipefail | codul de ieșire al unei înlănțuiri devine cel al ultimei comenzi din dreapta care a eșuat, sau 0 dacă n-a eșuat niciuna; set +o pipefail dezactivează setarea |
grep --line-buffered | grep scrie fiecare linie imediat; fără această opțiune, când ieșirea este un pipe, așteaptă până adună 4 KiB de text |
[student@fedora lab06]$ set -o pipefail
[student@fedora lab06]$ cut -d, -f2 nope.csv | sort
cut: nope.csv: No such file or directory
[student@fedora lab06]$ echo $?
1
[student@fedora lab06]$ set +o pipefail
- Cu
pipefail, eșecul luicutnu a mai rămas ascuns: înlănțuirea s-a terminat cu1.
Depanare
| Problemă | Soluție |
|---|---|
| O comandă așteaptă și promptul nu mai revine | Citește de la tastatură: ați uitat fișierul sau <. Apăsați Ctrl+D sau Ctrl+C |
tr: extra operand ‘fruits.txt’ | tr citește doar de la intrare: tr a-z A-Z < fruits.txt |
sort pune 100 înainte de 2 | Sortează ca text: adăugați -n, sau n după -k |
uniq lasă linii repetate | Liniile nu sunt una lângă alta: rulați întâi sort |
cut afișează linii goale sau câmpul greșit | Există mai mulți delimitatori la rând: comprimați-i cu tr -s sau folosiți awk |
cut -f2 afișează linia întreagă | Fără -d, delimitatorul este tab-ul, iar linia nu conține niciunul: dați delimitatorul cu -d |
cut: the delimiter must be a single character | -d primește un singur caracter: -d,, -d' ', -d: |
grep găsește linii la care nu vă așteptați | . și * sunt speciale într-un regex: scrieți \. pentru un punct adevărat, \* pentru un asterisc adevărat |
grep: warning: stray \ before d | \d nu înseamnă cifră în grep: folosiți [0-9] |
grep -E 'a+' merge, dar grep 'a+' nu găsește nimic | În expresiile regulate de bază, + este un caracter obișnuit: folosiți -E |
grep cu * dă rezultate ciudate sau caută în alte fișiere | Regex-ul nu este între ghilimele simple, iar shell-ul l-a expandat ca pe un glob |
sed: -e expression #1, char 8: unknown option to `s' | Textul conține /: folosiți alt separator, s|/usr|/opt| |
awk -F, '{ print $2 }' afișează linii goale | Delimitatorul este greșit: uitați-vă la o linie cu cat -A și dați-l pe cel corect cu -F |
awk "{ print $1 }" afișează linii întregi | Între ghilimele duble, shell-ul a înlocuit $1 cu nimic: folosiți ghilimele simple |
vim scrie litere în locuri ciudate sau nu scrie deloc | Sunteți în modul greșit: apăsați Esc, apoi i ca să scrieți |
E37: No write since last change (add ! to override) | vim nu iese fără să salveze: :wq salvează, :q! renunță la modificări |
vim: command not found | Folosiți vi sau instalați vim-enhanced (pe Ubuntu: vim) |
Exerciții
- 🧪 Primii pași (exercițiile 1 - 15): câte o idee pe rând, în ordinea din laborator, de făcut în laborator;
- 🏠 Mai departe (exercițiile 16 - 34): exerciții mai lungi, de făcut acasă; unele arată cum rulează împreună comenzile unei înlănțuiri, lucru explicat în Cum rulează o înlănțuire;
- 📝 Provocări (exercițiile 35 - 40): cele mai grele, asemănătoare cu cele de la examen.
Filtrele doar afișează: fișierele se schimbă numai prin >, sed -i sau un editor. Înainte să scrieți rezultatul peste
un fișier, uitați-vă la el pe ecran și nu redirectați niciodată ieșirea unei comenzi în propriul ei fișier de intrare:
sort f.txt > f.txt lasă f.txt gol, pentru că shell-ul golește fișierul pentru > înainte ca sort să înceapă să-l
citească.
🧪 Primii pași
Faceți aceste exerciții în ordine, în timpul laboratorului. Fiecare începe cu ce vrea să obțineți și exersează o
singură idee din laborator: dacă vă blocați, citiți secțiunea indicată la finalul exercițiului. Rulați comenzile în
~/lab06, dacă exercițiul nu spune altfel.
-
Alegeți-vă editorul: Alegeți
vim,nvim(Neovim),hx(Helix) sauemacsși începeți să-l învățați cu tutorialul lui, timp de 20 de minute. Continuați tutorialul acasă, în exercițiul 16.-
alegeți unul dintre cele patru editoare și instalați-l, dacă lipsește:
Editor Pe Fedora Pe Ubuntu Tutorialul vimsudo dnf install vim-enhancedsudo apt install vimvimtutornvimsudo dnf install neovimsudo apt install neovimnvim +Tutorhxsudo dnf install helixsudo snap install --classic helixhx --tutoremacssudo dnf install emacssudo apt install emacsemacs -nw -f help-with-tutorial -
porniți tutorialul și parcurgeți-l timp de 20 de minute: este un fișier text pe care îl modificați pe măsură ce îl citiți;
-
rețineți lecția la care v-ați oprit și ieșiți din tutorial fără să salvați.
💡 Fiecare tutorial începe cu deplasarea prin text și cu ieșirea din editor. Helix selectează întâi, apoi acționează: x selectează o linie, d o șterge. În Emacs, Ctrl+X Ctrl+C iese din editor;
-nwîl ține în terminal.Verificare: tutorialul se deschide în editor, la prima lecție; după 20 de minute vă puteți deplasa, puteți insera, șterge și ieși fără să vă uitați în el. → Editoare de text
-
-
Fișierele de lucru: Creați în
~/lab06fișierele pe care le folosesc celelalte exerciții.-
rulați comenzile de mai jos (copiați-le din browser cu Ctrl+C și lipiți-le în terminal cu Ctrl+Shift+V):
mkdir -p ~/lab06cd ~/lab06printf '%s\n' banana apple cherry apple kiwi banana apple > fruits.txtprintf '%s\n' 10 9 100 2 > numbers.txtprintf '%s\n' color colour cat category concatenate dog banana bat orange \gal goal gooooal notes.txt 2026-10-04 'call 0722 123 456' > words.txtprintf '%s\n' name,age,city Alice,30,Paris Bob,25,London Carol,22,Bucharest > students.csvprintf '%s\n' 'Alice 30 Paris' 'Bob 25 London' > people.txtprintf '%s\n' name,fruit,count alice,apple,3 bob,kiwi,1 carol,apple,2 \alice,banana,5 dan,apple,1 alice,apple,2 > orders.csvcat > access.log << 'END'10.0.0.7 GET /index.html 20010.0.0.9 GET /logo.png 40410.0.0.7 GET /about.html 20010.0.0.3 GET /old.html 40410.0.0.9 GET /favicon.ico 40410.0.0.5 GET /index.html 20010.0.0.9 GET /admin 40410.0.0.3 GET /old.html 404END -
listați fișierele din
~/lab06și numărați liniile fiecăruia cu o singură comandă.
Verificare:
~/lab06conține 7 fișiere:access.log(8 linii),fruits.txt(7),numbers.txt(4),orders.csv(7),people.txt(2),students.csv(4) șiwords.txt(15). → Numărarea:wc -
Filtre de linii
-
Capetele fișierului: Uitați-vă la bucăți dintr-un fișier, fără să-l afișați pe tot.
- afișați
fruits.txtcu numărul fiecărei linii; apoi afișați-l de la ultima linie la prima; - afișați primele 3 linii din
/etc/passwd, apoi doar ultima lui linie; - afișați doar linia a 5-a din
fruits.txt; - afișați
students.csvfără antet; - creați fișierul gol
live.log; într-un al doilea terminal, urmăriți-l; în primul terminal, adăugați în el, pe rând, liniilefirstșisecond; opriți urmărirea.
💡
man cat: căutaținumber;man tail: căutați+NUMșifollow; o linie se adaugă cuechoși>>(laboratorul 3).Verificare: liniile sunt numerotate de la
1la7, iartacîncepe cuapple; prima linie din/etc/passwdeste linia luiroot; al 5-lea fruct estekiwi; fără antet,students.csvîncepe cuAlice,30,Paris. Fiecare linie apare în al doilea terminal imediat ce o adăugați. → Afișarea unui fișier · Primele și ultimele linii - afișați
-
Sortați și numărați: Puneți liniile în ordinea potrivită și găsiți liniile care se repetă.
- sortați
numbers.txtca text, apoi ca numere, apoi ca numere, de la cel mai mare; - afișați studenții din
students.csv, fără antet, de la cel mai în vârstă la cel mai tânăr; apoi sortați-i după oraș; - afișați fiecare fruct din
fruits.txto singură dată, apoi doar fructele care apar exact o dată; - afișați fructul cel mai frecvent, împreună cu numărul de apariții, printr-o singură înlănțuire.
💡
man sort: căutațifield-separatorșiKEYDEF;man uniq: căutațiunique.Verificare:
10 100 2 9, apoi2 9 10 100, apoi100 10 9 2. După vârstă:Alice,Bob,Carol; după oraș:Carol(Bucharest),Bob(London),Alice(Paris). Fructele suntapple,banana,cherryșikiwi; doarcherryșikiwiapar o singură dată. Cel mai frecvent este3 apple. → Sortarea:sort· Numărarea liniilor repetate - sortați
Expresii regulate
-
Expresii regulate de bază: Descrieți linii printr-un tipar și găsiți-le în
words.txtcugrep.Pentru fiecare caz, scrieți întâi regex-ul pe hârtie, apoi verificați-l. Găsiți liniile care:
- se termină cu
l; - încep cu o cifră;
- conțin un
o, iar mai încolo în linie une; - au exact trei caractere, toate litere mici;
- au cel puțin un caracter care nu este nici literă mică, nici cifră.
💡 Tabelul din Expresii regulate de bază. La pasul 4, gândiți-vă la
^și$.Verificare:
gal,goal,gooooal;2026-10-04;concatenate,orange,notes.txt;cat,dog,bat,gal;notes.txt(din cauza lui.),2026-10-04(din cauza lui-) șicall 0722 123 456(din cauza spațiilor). → Expresii regulate de bază - se termină cu
-
Expresii regulate extinse: Scrieți tipare mai scurte cu
grep -Eși vedeți de ce un regex are nevoie de ghilimele.- găsiți liniile care conțin un
g, unul sau mai mulțio, apoial; - găsiți liniile care sunt exact
catsau exactdog; - găsiți liniile cu un număr de telefon: 4 cifre, un spațiu, 3 cifre, un spațiu, 3 cifre;
- creați fișierul gol
banana.txtși verificați culscă niciun alt fișier nu începe cuba; ghiciți întâi ce afișeazăgrep ba* words.txtșigrep 'ba*' words.txt, apoi rulați-le; ștergețibanana.txt.
💡 Tabelul din Expresii regulate extinse; la pasul 4, afișați cuvintele pe care le primește
grepcuecho grep ba* words.txt.Verificare:
goalșigooooal, dar nugal;catșidog, dar nucategory;call 0722 123 456. Fără ghilimele, shell-ul a transformatba*înbanana.txt, iargrepa căutat textulbanana.txt: nimic. Cu ghilimele,grepa primitba*, adică unburmat de oricâția:bananașibat. → Expresii regulate extinse · Expresii regulate - găsiți liniile care conțin un
-
Opțiunile lui
grep: Faceți-l pegrepsă afișeze exact ce vă trebuie: celelalte linii, doar o parte din ele sau doar un număr.- afișați setările din
/etc/login.defs(laboratorul 5), fără comentarii (liniile care încep cu#) și fără liniile goale; apoi numărați-le; - afișați linia setării
UMASK, împreună cu numărul ei; - afișați doar shell-ul fiecărui utilizator (textul de după ultimul
:) din baza de date a utilizatorilor; numărați câți utilizatori are fiecare shell; - numărați liniile din
words.txtcare conțincat, apoi afișați-le doar pe cele în carecateste un cuvânt întreg.
💡
man grep: căutațiinvert,line-number,only-matchingșiword-regexp; o linie goală înseamnă^$. Utilizatorii îi găsiți cugetent passwd(laboratorul 5).Verificare: setările sunt linii ca
UID_MIN 1000, câteva zeci;UMASKeste022. Cei mai mulți utilizatori aunologin(/sbin/nologinpe Fedora,/usr/sbin/nologinpe Ubuntu) și doar câțiva au/bin/bash.catapare în 3 linii, dar este cuvânt întreg doar încat. → Opțiunile luigrep - afișați setările din
Modificarea textului
-
Decupați coloane: Păstrați doar unele câmpuri, sau unele caractere, din fiecare linie.
- afișați numele și orașele din
students.csv, fără antet; - afișați numele și shell-ul fiecărui utilizator, din baza de date a utilizatorilor;
- afișați primele 3 caractere ale fiecărui fruct;
- afișați doar numele directorului curent, cu
pwd,revșicut.
💡
man cut: căutațidelimiter,fieldsșicharacters;/etc/passwdare 7 câmpuri, separate prin:.Verificare:
Alice,Paris,Bob,London,Carol,Bucharest; linii castudent:/bin/bash;ban,app,che, ...;lab06. → Extragerea coloanelor:cut· Inversarea și numerotarea - afișați numele și orașele din
-
Schimbați caractere: Schimbați, ștergeți și comprimați caractere cu
tr.- afișați
fruits.txtcu majuscule; - afișați fructele fără vocale;
- afișați cuvintele din
the quick brown foxcâte unul pe linie; - afișați vârsta fiecărei persoane din
people.txt, cutrșicut; - afișați directoarele din
PATHcâte unul pe linie și numărați-le.
💡
man tr: căutațideleteșisqueeze;trcitește doar de la intrare.Verificare:
BANANA, ...;bnn,ppl,chrry,ppl,kw,bnn,ppl; 4 linii;30și25; câte un director pe linie, printre ele/usr/bin. → Schimbarea caracterelor:tr - afișați
-
Înlocuiți text: Schimbați cuvinte și bucăți de linii cu
sed, fără să modificați fișierele.- înlocuiți
applecupearînfruits.txt; apoi verificați căfruits.txtnu s-a schimbat; - afișați linia cu telefonul din
words.txt, cu fiecare cifră înlocuită cu#; - afișați
students.csvcu tab-uri în loc de virgule, apoi extrageți a doua coloană fără-d; - afișați linia
notes.txtdinwords.txtfără extensie; - afișați directorul utilizatorului, cu
/homeînlocuit de/users.
💡 Înlocuirea textului:
sed;\teste un tab; la pasul 5, folosiți alt separator decât/.Verificare: de trei ori
pear, iarfruits.txtconține totapple;call #### ### ###;age,30,25,22;notes;/users/student. → Înlocuirea textului:sed - înlocuiți
Numărare și calcul
-
Numărați: Numărați liniile, cuvintele și caracterele unui text.
- numărați liniile, cuvintele și octeții din
words.txt; apoi doar liniile, fără numele fișierului; - numărați utilizatorii sistemului;
- numărați caracterele și octeții din
Iași.
💡
man wc: căutațichars.Verificare:
15 18 116 words.txt, apoi15; câteva zeci de utilizatori;Iașiîmpreună cu sfârșitul de linie înseamnă 5 caractere, dar 6 octeți:șocupă 2 octeți. → Numărarea:wc - numărați liniile, cuvintele și octeții din
-
Calcule cu
awk: Răspundeți cuawkla întrebări despre comenzile dinorders.csv.- afișați numele și cantitatea din fiecare comandă, fără antet;
- calculați câte fructe a comandat
aliceîn total; - calculați cantitatea medie din comenzile de mere;
- afișați comenzile de cel puțin 2 fructe, apoi numărați-le;
- afișați numele și UID-ul utilizatorilor care au UID-ul cel puțin
1000, din baza de date a utilizatorilor.
💡 Calculul:
awkare tot ce vă trebuie; UID-ul este câmpul 3 din baza de date a utilizatorilor. Săriți peste antet cuNR > 1:awkcompară textulcountcu un număr ca pe un text, iar"count" >= 2este adevărat.Verificare:
alice 3,bob 1, ...;10;2; 4 comenzi;student 1000, dar șinobody 65534. → Calculul:awk
O înlănțuire
-
Citiți un jurnal: Răspundeți la întrebări despre cererile din
access.log, cu înlănțuiri pe care le construiți comandă cu comandă.- afișați pagina fiecărei cereri (al treilea câmp);
- afișați de câte ori a fost cerută fiecare pagină, întâi cea mai cerută;
- afișați adresele care au cerut o pagină inexistentă (codul de stare
404), fiecare o singură dată; - numărați cererile care s-au terminat cu
404.
💡 O înlănțuire, pas cu pas; uitați-vă la rezultat după fiecare comandă.
Verificare: 8 pagini;
/index.htmlși/old.htmlau fost cerute de două ori, celelalte o dată;10.0.0.3și10.0.0.9;5. → O înlănțuire, pas cu pas · Filtre
Coduri de ieșire
-
A mers?: Citiți codul de ieșire al unei comenzi și rulați o comandă doar dacă alta a reușit sau a eșuat.
- ghiciți întâi codul de ieșire al fiecărei comenzi, apoi verificați-l:
grep -q apple fruits.txt,grep -q mango fruits.txt,grep apple nope.txt,ls /nope,trueșifalse; - porniți
sleep 100, opriți-l cu Ctrl+C și afișați-i codul de ieșire; - afișați
founddoar dacăcherryse află înfruits.txt; apoi afișațimissingdoar dacămangonu se află în el; - creați directorul
saveși, doar dacă ați reușit, copiați în elorders.csv, totul pe o singură linie; rulați aceeași linie încă o dată.
💡 Coduri de ieșire și Legarea comenzilor;
man ls: căutațiExit status.Verificare:
0,1,2,2,0,1;sleepse termină cu130:128 + 2, pentruSIGINT.found, apoimissing. A doua oară,mkdireșuează cuFile exists, iarcpnu mai rulează. → Coduri de ieșire · Legarea comenzilor - ghiciți întâi codul de ieșire al fiecărei comenzi, apoi verificați-l:
Editoare de text
-
Două editoare: Scrieți un fișier cu
nano, apoi modificați-l cuvim.- cu
nano, creațitodo.txtcu trei linii:buy milk,learn vimșicall bob; tăiați ultima linie și lipiți-o deasupra primei; salvați și ieșiți; - deschideți
todo.txtcuvim; ștergeți linialearn vim, apoi dați undo; adăugați la final liniapractice awk; înlocuițimilkcubread, printr-o comandă; salvați și ieșiți; - deschideți-l din nou, ștergeți o linie și ieșiți fără să salvați;
- afișați
todo.txt.
💡 Tabelele din
nanoșivim; învim, uitați-vă mereu la ultima linie ca să știți în ce mod sunteți.Verificare:
todo.txtare 4 linii:call bob,buy bread,learn vimșipractice awk. →nano·vim - cu
🏠 Mai departe
Fiecare exercițiu începe cu scopul lui; comenzile le alegeți voi. La final, verificați că ați atins scopul, nu doar
că fiecare comandă a mers. Exercițiile folosesc fișierele din ~/lab06 de la Primii pași.
-
Editorul ales: esențialul: Continuați tutorialul editorului ales la exercițiul 1, până știți destul ca să-l folosiți zilnic, apoi lucrați cu el pe un fișier real.
-
instalați editorul, dacă lipsește de pe calculatorul vostru:
Editor Pe Fedora Pe Ubuntu Tutorialul vimsudo dnf install vim-enhancedsudo apt install vimvimtutornvimsudo dnf install neovimsudo apt install neovimnvim +Tutorhxsudo dnf install helixsudo snap install --classic helixhx --tutoremacssudo dnf install emacssudo apt install emacsemacs -nw -f help-with-tutorial -
porniți din nou tutorialul, mergeți la lecția la care v-ați oprit în laborator și parcurgeți-l până la finalul lecțiilor de mai jos; de restul tutorialului nu aveți nevoie încă:
vim,nvim: lecțiile 1 - 6, până când știțio,yșip(lecția 7 este despre help și setări);hx: capitolele 1 - 6, până când știți comanda de înlocuire, r;emacs: secțiunile până la Searching, inclusiv;
-
ieșiți din tutorial fără să salvați;
-
deschideți cu editorul ales
todo.txtde la exercițiul 15, adăugați la final liniause vim(sauuse nvim,use hx,use emacs), salvați și ieșiți; afișațitodo.txt.
💡 Fiecare tutorial începe cu deplasarea prin text și cu ieșirea din editor. Helix selectează întâi, apoi acționează: x selectează o linie, d o șterge. În Emacs, Ctrl+X Ctrl+C iese din editor;
-nwîl ține în terminal.Verificare: ați parcurs lecțiile editorului ales și vă puteți deplasa, puteți insera, șterge, copia, lipi, da undo, căuta, salva și ieși fără să vă uitați în tutorial.
todo.txtse termină cu linia editorului vostru, dupăpractice awk. → Editoare de text -
Filtre de linii și căutare
-
Comenzile preferate: Folosiți terminalul de șase săptămâni. Aflați care sunt cele 5 comenzi pe care le rulați cel mai des.
- afișați istoricul shell-ului și găsiți câmpul care conține numele comenzii;
- afișați cele mai folosite 5 comenzi, fiecare cu numărul de rulări, întâi cea mai folosită.
💡
help history; fiecare linie dinhistoryîncepe cu un număr.Verificare: 5 linii ca
42 ls, cu numere descrescătoare; de obicei,lsșicdsunt pe primele locuri. Fiecare terminal își adaugă comenzile în~/.bash_historyabia când se închide, așa că un terminal nou nu știe comenzile celor încă deschise. → Numărarea liniilor repetate · Calculul:awk -
Cele mai mari programe: Discul calculatorului este aproape plin. Găsiți cele mai mari 5 fișiere din
/usr/bin, cu dimensiuni ușor de citit.- listați
/usr/binîn format lung și sortați liniile după dimensiune, al 5-lea câmp, ca număr; păstrați cele mai mari 5; - afișați doar dimensiunea și numele lor;
- refaceți totul cu dimensiunile scrise ca
2.1Mși sortați-le corect.
💡
man sort: căutațiKEYDEFșihuman;man ls: căutațihuman.Verificare: aceleași 5 fișiere la pașii 1 și 3, în aceeași ordine; la pasul 3,
sort -nsingur ar citi900Kca900și2.1Mca2.1și ar crede că900Keste mai mare. → Sortarea:sort· Calculul:awk - listați
-
Un formular de înscriere: Un formular a salvat tot ce au tastat oamenii, fără nicio verificare. Păstrați doar numerele de telefon și adresele de e-mail valide.
Creați
contacts.txt:cat > ~/lab06/contacts.txt << 'END'07221234560722 123 456+40722123456072212345072212345670312345678ana.pop@upb.robob@gmailcarol@@yahoo.comdave_99@stud.upb.roerin@example.comEND- afișați numerele de mobil:
07urmat de încă 8 cifre, nimic altceva pe linie; - acceptați și numerele scrise cu
+4în față; - afișați adresele de e-mail: litere mici, cifre,
.sau_, apoi un singur@, apoi un domeniu format din litere mici și puncte, care se termină cu un.urmat de câteva litere; - numărați, cu un singur
grep, liniile care nu sunt nici număr de telefon, ca la pasul 2, nici adresă de e-mail.
💡 Expresii regulate extinse; un
+care este caracter obișnuit se scrie\+.Verificare:
0722123456; apoi și+40722123456;ana.pop@upb.ro,dave_99@stud.upb.roșierin@example.com;6linii nu sunt nici una, nici alta. → Expresii regulate extinse · Opțiunile luigrep - afișați numerele de mobil:
Coloane și calcule
-
Numele de la secretariat: Secretariatul a exportat numele sub forma
Popescu, Ana, dar sistemul nou vreaAna Popescuși câte o adresă pentru fiecare student.Creați
names.txtcuprintf '%s\n' 'Popescu, Ana' 'Ionescu, Mihai' 'Georgescu, Ioana' > names.txt:- afișați fiecare nume sub forma
Ana Popescu, cu un singursed; - sortați rezultatul după prenume;
- afișați o adresă de e-mail pentru fiecare student, de forma
ana.popescu@upb.ro, numai cu litere mici.
💡
man sed: căutați\1; într-un regex extins,( )reține textul cu care s-a potrivit, iar\1,\2îl pun înapoi în textul nou.Verificare:
Ana Popescu,Mihai Ionescu,Ioana Georgescu; sortat:Ana,Ioana,Mihai;ana.popescu@upb.ro,mihai.ionescu@upb.ro,ioana.georgescu@upb.ro. → Înlocuirea textului:sed· Schimbarea caracterelor:tr - afișați fiecare nume sub forma
-
Cuvintele manualului: Ce cuvinte folosește cel mai des manualul lui
bashși câte cuvinte diferite conține?- afișați textul din
man bashcâte un cuvânt pe linie: orice secvență de caractere care nu sunt litere devine un singur sfârșit de linie; - transformați toate cuvintele în litere mici și afișați cele mai frecvente 10, cu numărul lor de apariții;
- numărați cuvintele diferite.
💡
man tr: căutațicomplement; trimisă într-un pipe, pagina de manual este text simplu.Verificare:
theeste primul, la mare distanță; urmează cuvinte scurte caa,is,toșiof. Există câteva mii de cuvinte diferite. → Schimbarea caracterelor:tr· Numărarea liniilor repetate - afișați textul din
-
Memoria browserului: Calculatorul merge greu și îl bănuiți pe Firefox. Aflați câtă memorie folosesc împreună toate procesele lui.
Deschideți Firefox cu câteva tab-uri, apoi:
- listați memoria (
RSS) și linia de comandă completă a fiecărui proces și păstrați-le doar pe cele ale lui Firefox; numărați-le; - adunați-le memoria și afișați-o în MiB;
- afișați cele 3 procese din sistem care folosesc cea mai multă memorie.
💡
man ps: căutațirss(unitatea de măsură este KiB) șiargs; și un tab din Firefox este un proces, care nu se numeștefirefox, dar arefirefoxîn linia de comandă. Comandagrep firefoxare și eafirefoxîn linia de comandă, așa că se găsește pe sine;grep '[f]irefox'se potrivește cu aceleași procese, dar nu și cu el însuși.Verificare: Firefox are mai multe procese, câte unul la câteva tab-uri; împreună folosesc câteva sute de MiB. De obicei, Firefox se numără printre cele mai mari 3 procese. → Calculul:
awk· Listarea proceselor - listați memoria (
-
Notele de la examen: Asistentul are nevoie de un raport despre examen, pe baza unui fișier cu note.
Creați
grades.csvcuprintf '%s\n' name,grade ana,9 bob,4 carol,7 dave,10 erin,3 grace,5 mallory,6 > grades.csv, apoi calculați cuawk:- câți studenți au promovat (cu o notă de cel puțin
5); - media tuturor notelor și media celor care au promovat;
- nota cea mai mare și studentul care a luat-o;
- numele studenților care nu au promovat, în ordine alfabetică.
💡 Săriți peste antet la fiecare pas, cu
NR > 1:awkcompară textulgradecu un număr ca pe un text, așa că antetul ar „promova” și ar deveni chiar nota cea mai mare. O variabilă poate ține minte valoarea cea mai mare de până atunci:NR > 1 && $2 > max { max = $2 }.Verificare:
5;6.28571și7.4;dave 10;bobșierin. → Calculul:awk - câți studenți au promovat (cu o notă de cel puțin
-
Auditul utilizatorilor: Scrieți raportul despre utilizatorii sistemului, așa cum l-ar face lunar un administrator.
Folosiți baza de date a utilizatorilor:
- afișați fiecare shell și câți utilizatori îl au, întâi cel mai folosit;
- numărați utilizatorii de sistem (cu UID de la
1la999); - afișați numele și directorul utilizatorilor obișnuiți (cu UID de la
1000la60000).
💡
man login.defs: căutațiUID_MAX; condițiile dinawkpot folosi&&.Verificare:
nologineste shell-ul cel mai folosit; există câteva zeci de utilizatori de sistem; utilizatorii obișnuiți suntstudentși toți utilizatorii din laboratorul 5 care mai există, cu directorul în/home.nobody(65534) nu este un utilizator obișnuit. → Calculul:awk· Extragerea coloanelor:cut
Coduri de ieșire
-
Ghiciți lanțul: Învățați să citiți
&&și||fără să rulați comenzile.Scrieți întâi pe hârtie ce afișează fiecare linie, apoi verificați:
true && echo A || echo Bfalse && echo A || echo Btrue || echo A && echo Bfalse || false && echo C; echo $?true && false || echo D
Verificare:
A;B;B; nimic, apoi1;D. Shell-ul citește de la stânga la dreapta, iar fiecare&&sau||se uită la codul de ieșire al ultimei comenzi rulate înaintea lui: la linia 5 se afișeazăD, deși prima comandă a reușit. → Legarea comenzilor -
Ce înseamnă numerele: Aflați ce spun codurile de ieșire, dincolo de „succes” și „eroare”.
- căutați în manual ce înseamnă
1și2pentrulsși obțineți-le pe fiecare; - porniți
sleep 100, încheiați-l cukilldintr-un alt terminal și afișați-i codul de ieșire; repetați cukill -9; - rulați
bash -c 'exit 42'și afișați-i codul de ieșire; apoibash -c 'exit 300'.
💡
man ls: căutațiExit status; ascundeți rezultatul lung al luils -Rcu> /dev/null 2>&1;kill -l 15afișează numele semnalului15; un cod de ieșire ocupă un octet.Verificare:
ls /nopese termină cu2;ls -R /etcse termină cu1, pentru că unele directoare din el nu pot fi citite.killdă143(128 + 15,SIGTERM),kill -9dă137(128 + 9,SIGKILL).42, apoi44:300nu încape într-un octet și se păstrează doar300 - 256. → Coduri de ieșire · Semnale - căutați în manual ce înseamnă
-
O modificare prudentă: Trebuie să schimbați
kiwiînmangodirect în fișierulorders.csv. Faceți-o astfel încât să puteți reveni oricând.- pe o singură linie: copiați
orders.csvînorders.bak; doar dacă a reușit copierea, modificați fișierul cused -i; afișațichangeddacă amândouă au reușit, altfelnot changed; - verificați conținutul ambelor fișiere;
- rulați din nou aceeași linie, dar copiați în
/nope/orders.bak; - readuceți
orders.csvla forma originală, dinorders.bak.
💡 Înlocuirea textului:
sedși Legarea comenzilor.Verificare: după pasul 1,
orders.csvconținebob,mango,1, iarorders.bakconținebob,kiwi,1. La pasul 3,cpeșuează,sednu rulează și se afișeazănot changed. La final,grep -c kiwi orders.csvafișează1. → Legarea comenzilor · Înlocuirea textului:sed - pe o singură linie: copiați
Cum rulează o înlănțuire
-
Procesele unei înlănțuiri: Vedeți cum comenzile unei înlănțuiri rulează împreună, ca un singur job.
- în al doilea terminal, afișați PID-ul shell-ului, apoi rulați
sleep 300 | sleep 301 | cat; - în primul terminal, afișați arborele de procese al celui de-al doilea shell, cu PID-uri; listați aceste procese cu PID-ul, PPID-ul, grupul de procese, starea și numele lor;
- opriți înlănțuirea cu Ctrl+Z și listați-le din nou; continuați-o cu
fgși încheiați-o cu Ctrl+C.
💡
man pstree: căutațipid;man ps: căutațipgidșistate.Verificare: cele trei comenzi sunt copiii aceluiași
bash, pornite în același timp, și au același grup de procese: PID-ul primuluisleep. Toate sunt în stareaS(în așteptare); după Ctrl+Z, toate suntT(oprite); Ctrl+C le încheie pe toate trei. → Cum rulează o înlănțuire · Foreground și background - în al doilea terminal, afișați PID-ul shell-ului, apoi rulați
-
Pe urmele pipe-ului: Găsiți în
/procpipe-ul dintre două comenzi.- în al doilea terminal, rulați
sleep 300 | cat; - în primul terminal, aflați PID-urile lui
sleepșicatși afișați unde duc intrările (0) și ieșirile (1) ale amândurora; - încheiați înlănțuirea.
💡
man pgrep;man readlink; descriptorii de fișier ai unui proces se află în/proc/<PID>/fd(laboratorul 3).Verificare: ieșirea lui
sleepși intrarea luicatsunt acelașipipe:[...], cu același număr; intrarea luisleepși ieșirea luicatsunt terminalul,/dev/pts/.... → Cum rulează o înlănțuire · Sistemul de fișiere/proc - în al doilea terminal, rulați
-
Cine termină primul: Aflați ce se întâmplă cu o comandă al cărei cititor s-a oprit din citit.
Pentru fiecare linie, ghiciți întâi codurile de ieșire ale celor două comenzi, apoi afișați-le cu
PIPESTATUS:yes | head -n 3;seq 5 | sleep 2;seq 100000 | sleep 2.
💡
kill -l 13;seq 100000 | wc -carată cât text scrieseq; într-un pipe încap 64 KiB.Verificare:
141 0:yesa primitSIGPIPE.0 0: cele 5 linii scurte încap în pipe, iarseqs-a terminat înaintea luisleep.141 0: aproximativ 575 KiB nu încap, așa căseqa așteptat un cititor; cândsleeps-a terminat fără să citească nimic,seqa primitSIGPIPE. → Cum rulează o înlănțuire -
Un eșec la mijloc: În fiecare noapte, o înlănțuire numără clienții magazinului. Într-o noapte fișierul lipsea, iar raportul a spus
0, fără nicio eroare. Faceți înlănțuirea să spună adevărul.- rulați
cut -d, -f1 nope.csv | sort -u | wc -l; apoi, cu un singurecho, afișați codul ei de ieșire și codurile de ieșire ale fiecărei comenzi; - adăugați
&& echo ok || echo faileddupă înlănțuire; - activați
pipefailși repetați pasul 2; apoi dezactivați-l.
💡 Cum rulează o înlănțuire; și
echoeste o comandă: după el,$?șiPIPESTATUSdescriuecho-ul, nu înlănțuirea.Verificare: înlănțuirea afișează
0și se termină cu0, darPIPESTATUSeste1 0 0; fărăpipefailspuneok, cupipefailspunefailed. → Cum rulează o înlănțuire · Codul de ieșire al unei înlănțuiri - rulați
-
Un jurnal în timp real: Urmăriți cererile care se termină cu
404pe măsură ce sosesc, și doar adresele lor.- în al doilea terminal, urmăriți
live.logși păstrați doar liniile care conțin404; - în primul terminal, adăugați în
live.loglinia10.0.0.9 GET /x 404, apoi linia10.0.0.7 GET / 200; - în al doilea terminal, adăugați
cutla final, ca să păstrați doar adresa; adăugați încă o linie cu404; - reparați înlănțuirea de la pasul 3, astfel încât adresa să apară imediat.
💡 Cum rulează o înlănțuire;
man grep: căutațiline-buffered.Verificare: la pasul 2 apare imediat doar linia cu
404. La pasul 3 nu apare nimic: acum ieșirea luigrepmerge într-un pipe, iargrepașteaptă până adună 4 KiB de text. Cugrep --line-buffered, adresa apare pe loc. → Cum rulează o înlănțuire · Primele și ultimele linii - în al doilea terminal, urmăriți
Editoare de text
-
Editorul ales, pe un fișier real: Modificați un fișier cu editorul învățat la exercițiile 1 și 16, fără să retastați liniile care rămân la fel.
- copiați
students.csvînclass.csvși deschideți-l cu editorul ales; - adăugați la final linia
Dave,27,Cluj; - copiați linia lui
Bobși lipiți copia sub ea; transformați copia înErin,24,Iasi; - înlocuiți fiecare
,cu;, printr-o singură comandă; salvați, ieșiți și afișați fișierul.
💡 Alegeți editorul:
- vim
- nvim
- hx
- emacs
Pas Taste deschideți fișierul vim class.csvadăugați o linie la final G sare la ultima linie, o deschide o linie nouă dedesubt; tastați-o, apoi Esc copiați o linie și lipiți-o dedesubt pe Bob: yy copiază linia, p o lipește dedesubtschimbați o linie întreagă pe copie: cc șterge textul liniei; tastați-l pe cel nou, apoi Esc înlocuiți în tot fișierul :%s/,/;/g;:sfără%modifică doar linia curentăsalvați și ieșiți :wqNeovim are aceleași taste ca
vim.Pas Taste deschideți fișierul nvim class.csvadăugați o linie la final G sare la ultima linie, o deschide o linie nouă dedesubt; tastați-o, apoi Esc copiați o linie și lipiți-o dedesubt pe Bob: yy copiază linia, p o lipește dedesubtschimbați o linie întreagă pe copie: cc șterge textul liniei; tastați-l pe cel nou, apoi Esc înlocuiți în tot fișierul :%s/,/;/g;:sfără%modifică doar linia curentăsalvați și ieșiți :wqPas Taste deschideți fișierul hx class.csvadăugați o linie la final ge sare la ultima linie, o deschide o linie nouă dedesubt; tastați-o, apoi Esc copiați o linie și lipiți-o dedesubt pe Bob: x selectează linia, y o copiază, p o lipește dedesubtschimbați o linie întreagă pe copie: x selectează linia, _ lasă deoparte sfârșitul ei, c o șterge; tastați-o pe cea nouă, apoi Esc înlocuiți în tot fișierul % selectează tot fișierul, s ,Enter selectează fiecare,din el, r; le înlocuiește pe toatesalvați și ieșiți :wqPas Taste deschideți fișierul emacs -nw class.csvadăugați o linie la final Alt+> sare la sfârșitul fișierului; tastați linia copiați o linie și lipiți-o dedesubt la începutul liniei lui Bob(Ctrl+A): Ctrl+K de două ori taie linia, Ctrl+Y de două ori o lipește la loc și încă o dată, ca copieschimbați o linie întreagă pe copie (Ctrl+P urcă o linie), la începutul ei: Ctrl+K taie textul; tastați-l pe cel nou înlocuiți în tot fișierul Alt+< sare la început, Alt+% ,Enter;Enter vă întreabă la fiecare potrivire; ! le înlocuiește pe toatesalvați și ieșiți Ctrl+X Ctrl+S, apoi Ctrl+X Ctrl+C Verificare:
class.csvare 6 linii:name;age;city,Alice;30;Paris,Bob;25;London,Erin;24;Iasi,Carol;22;BucharestșiDave;27;Cluj. → Editoare de text - copiați
Curățenie
-
Curățenie: Lăsați directorul utilizatorului așa cum era înainte de laborator.
- ștergeți
~/lab06; - dacă
set -o pipefailmai este activ într-un shell, închideți terminalul respectiv.
Verificare:
ls ~nu mai afișeazălab06; într-un terminal nou,set -o | grep pipefailafișeazăpipefail off. → Cum rulează o înlănțuire - ștergeți
📝 Provocări
Aceste exerciții seamănă cu cele de la examen. Fiecare vă dă un rezultat de obținut, dar nu și pașii: comenzile le alegeți voi. Fiecare se încheie cu Verificarea după care va fi notat. Unele au nevoie de Cum rulează o înlănțuire.
Toate provocările pornesc de la aceeași configurație, pe care o veți găsi și la examen: directorul ~/exam, cu patru
fișiere. web.log conține câte o cerere pe linie, cu 7 câmpuri separate printr-un spațiu: adresa, data, ora, metoda,
pagina, codul de stare și numărul de octeți trimiși. Copiați și rulați comenzile de mai jos înainte de prima provocare;
rulați-le din nou ca să recuperați fișierele originale:
mkdir -p ~/exam
cd ~/exam
cat > web.log << 'END'
10.0.0.7 2026-11-02 10:15:01 GET /index.html 200 5120
10.0.0.9 2026-11-02 10:15:04 GET /logo.png 404 0
10.0.0.7 2026-11-02 10:15:09 GET /about.html 200 2048
10.0.0.3 2026-11-02 10:16:12 GET /old.html 404 0
10.0.0.9 2026-11-02 10:16:30 GET /favicon.ico 404 0
10.0.0.5 2026-11-02 10:17:45 POST /login 200 512
10.0.0.9 2026-11-02 10:18:02 GET /admin 403 0
10.0.0.3 2026-11-02 10:18:40 GET /old.html 404 0
10.0.0.12 2026-11-02 11:02:11 GET /index.html 200 5120
10.0.0.5 2026-11-02 11:03:27 GET /exam.pdf 200 734003
10.0.0.9 2026-11-02 11:04:51 POST /login 401 0
10.0.0.9 2026-11-02 11:04:53 POST /login 401 0
10.0.0.9 2026-11-02 11:04:55 POST /login 401 0
10.0.0.7 2026-11-02 11:20:00 GET /index.html 200 5120
10.0.0.12 2026-11-02 12:01:10 GET /exam.pdf 200 734003
10.0.0.7 2026-11-02 12:30:44 GET /contact.html 200 1024
10.0.0.5 2026-11-02 12:31:02 POST /login 401 0
END
printf '%s\n' 'B 123 ABC' 'B 12 XYZ' 'IF 07 UPB' 'CJ 123 ABC' 'IS 99 ab' 'b 100 USO' \
'TM 05 LNX' 'B1 23 ABC' 'AG 7 OOO' > plates.txt
printf '%s\n' name,lab,exam ana,4.5,3.5 bob,2,1.5 carol,3,4 dave,5,4.5 erin,1.5,2 \
grace,3.5,1 mallory,4,2.5 > grades.csv
printf '%s\n' '# the settings of the exam server' port=8080 '# host=localhost' \
host=0.0.0.0 debug=true users=ana,bob,carol > settings.conf
Când ați terminat toate provocările, ștergeți totul cu rm -rf ~/exam.
-
Cele mai active adrese: Aflați cine folosește cel mai mult serverul și câți octeți trimite acesta.
Cu câte o singură înlănțuire pentru fiecare:
- afișați cele 3 adrese cu cele mai multe cereri, fiecare cu numărul ei de cereri, întâi cea mai activă;
- afișați numărul total de octeți trimiși de server;
- afișați numărul de octeți trimiși către
10.0.0.12.
Verificare: cele trei rezultate sunt exact:
6 10.0.0.94 10.0.0.73 10.0.0.5apoi
1486950, apoi739123. → Filtre · Calculul:awk -
Cine ghicește parole: O autentificare eșuată este o cerere
POSTpentru/logincare se termină cu401. Găsiți adresele care au eșuat la autentificare de cel puțin 3 ori și aflați cât de încărcat a fost serverul în fiecare oră.- afișați fiecare adresă cu cel puțin 3 autentificări eșuate, împreună cu numărul de eșecuri;
- afișați numărul de cereri din fiecare oră, în ordinea orelor.
Verificare: pasul 1 afișează exact
3 10.0.0.9(10.0.0.5a eșuat o singură dată); pasul 2 afișează exact:→ Calculul:8 106 113 12awk· Extragerea coloanelor:cut -
Numere de înmatriculare: Păstrați doar numerele de înmatriculare valide din
plates.txt, cu un singurgrepși o singură expresie regulată.Un număr valid conține, separate prin câte un singur spațiu:
- județul:
B(București) sau două majuscule; - un număr: 2 sau 3 cifre pentru
B, exact 2 cifre pentru celelalte județe; - trei majuscule.
Pe linie nu mai poate fi nimic altceva.
Verificare: comanda afișează exact
B 123 ABC,B 12 XYZ,IF 07 UPBșiTM 05 LNX, iar aceeași comandă cu-cafișează4. → Expresii regulate extinse - județul:
-
Notele finale:
grades.csvconține, pentru fiecare student, nota de la laborator și nota de la examen. Nota finală este suma lor. Un student promovează cu o notă finală de cel puțin5și o notă la examen de cel puțin2.5.Cu o singură înlănțuire, afișați numele și nota finală ale fiecărui student promovat, întâi nota cea mai mare.
Verificare: rezultatul este exact
dave 9.5,ana 8,carol 7șimallory 6.5;graceare4.5, iarbobșierinau mai puțin, așa că nu apar. → Calculul:awk· Sortarea:sort -
Ghiciți codurile de ieșire: Prevedeți ce afișează fiecare linie și cu ce coduri de ieșire se termină, apoi demonstrați fiecare răspuns.
În
~/exam, completați întâi tabelul pe hârtie; apoi rulați fiecare linie, urmată deecho $?sau, la liniile 4 și 6, deecho "${PIPESTATUS[@]}":Linia Afișează Cod(uri) de ieșire 1. grep -c ' 404 ' web.log2. grep -c ' 500 ' web.log3. grep -q ' 500 ' web.log && echo yes || echo no4. cut -d' ' -f1 web.log nope.log | sort -u | wc -l5. aceeași linie, după set -o pipefail6. yes | head -n 1 > /dev/null7. mkdir -p backup && cp nope.log backup/ && echo saved || echo failedDezactivați
pipefaildupă linia 5.Verificare:
→ Coduri de ieșire · Legarea comenzilor · Cum rulează o înlănțuireAfișează Cod(uri) de ieșire 1. 402. 01:grepnu a găsit nimic, chiar dacă a afișat un număr3. no0, codul de ieșire al luiecho no4. o eroare de la cut, apoi51 0 0:cuta eșuat, dar a cititweb.log5. o eroare de la cut, apoi516. nimic 141 0:yesa primitSIGPIPE7. o eroare de la cp, apoifailed0, codul de ieșire al luiecho failed -
Configurare cu
vim: Modificațisettings.confdoar cuvim, fără să retastați liniile care rămân la fel.La final, fișierul trebuie să conțină exact aceste linii, în această ordine:
port=80host=0.0.0.0debug=falseusers=ana,bob,carol,davetimeout=30💡 În
vim,:help :gexplică cum rulați o comandă, de exemplud, pe fiecare linie care se potrivește cu un regex;:help Aexplică cum adăugați text la sfârșitul unei linii.Verificare:
cat -A settings.confafișează cele 5 linii, fiecare terminată cu$, fără spații înainte de$și fără linii goale. →vim
Întrebări de recapitulare
Folosiți ultimele 5 minute ale laboratorului ca să răspundeți la aceste întrebări împreună cu colegii și cu asistentul. La ultimele două nu există răspunsuri greșite.
- Ce este un filtru? De ce poate fi ieșirea oricărui filtru intrarea oricărui alt filtru?
- De ce are nevoie
uniqdesortînaintea lui? De ce punesort100înainte de2și cum reparați asta? - Care este diferența dintre
*dintr-un glob și*dintr-o expresie regulată? De ce puneți un regex între ghilimele simple? - Când folosiți
cutși cândawk? Ce se întâmplă cucutcând câmpurile sunt separate prin mai multe spații? - Care este diferența dintre
trșised? - Ce înseamnă codul de ieșire
0? Ce fac&&și||cu el? - Ce cod de ieșire are o înlănțuire? Ce poate ascunde?
- Cum ieșiți din
vimfără să salvați? - Ce filtru v-a surprins cel mai mult azi?
- Ce editor veți folosi de acum înainte și de ce?
Extra
column:column -t -s, students.csvaliniază un fișier CSV sub formă de tabel, ca să se citească ușor. →man columnjq: multe programe și servicii web scriu JSON în loc de linii;jqeste filtrul pentru acest format, cu propriul lui mic limbaj. Instalați-l cusudo dnf install jq(pe Ubuntu:sudo apt install jq). →man jq- Alte editoare:
helix(hx --tutor) șiemacs(Ctrl+H, apoi T) au propriile tutoriale, cavimtutor; Visual Studio Code și Zed pot folosi tastele luivim.