This shows you the differences between two versions of the page.
unixmix:capitole:capitol-06 [2013/07/10 10:58] alexef created |
unixmix:capitole:capitol-06 [2014/09/11 12:25] (current) razvan [Exerciții] |
||
---|---|---|---|
Line 1: | Line 1: | ||
= Filtre de text = | = Filtre de text = | ||
+ | |||
+ | [[https://docs.google.com/presentation/d/1btwpQIcgu5F9Upw0EKD7ufhzgLycuacE3q07N-_f_6w/pub?start=false&loop=false&delayms=3000|Slide-uri de prezentare]] | ||
+ | |||
+ | == Tutorial == | ||
+ | |||
+ | Pentru tutorial, vom folosi următorul text: | ||
+ | <code> | ||
+ | root:x:0:0:root:/root:/bin/bash | ||
+ | daemon:x:1:1:daemon:/usr/sbin:/bin/sh | ||
+ | bin:x:2:2:bin:/bin:/bin/sh | ||
+ | sys:x:3:3:sys:/dev:/bin/sh | ||
+ | |||
+ | games:x:5:60:games:/usr/games:/bin/sh | ||
+ | mail:x:8:8:mail:/var/mail:/bin/sh | ||
+ | www-data:x:33:33:www-data:/var/www:/bin/sh | ||
+ | irc:x:39:39:ircd:/var/run/ircd:/bin/sh | ||
+ | |||
+ | nobody:x:65534:65534:nobody:/nonexistent:/bin/sh | ||
+ | gdm:x:106:114:Gnome Display Manager:/var/lib/gdm:/bin/false | ||
+ | |||
+ | kernoops:x:108:65534:Kernel Oops Tracking Daemon,,,:/:/bin/false | ||
+ | ieu:x:1000:1000:ieu,,,:/home/ieu:/bin/bash | ||
+ | </code> | ||
+ | |||
+ | * Copiați textul de mai sus și salvați-l într-un fișier numit ''passwd'' aflat în directorul home al utilizatorului ''student''. | ||
+ | ** Fișierul are o structură asemănătoare ''/etc/passwd'' (informații despre utilizatorii sistemului) | ||
+ | *** nume utilizator | ||
+ | *** dacă parola este în ''/etc/shadow'' criptată | ||
+ | *** UID, GID | ||
+ | *** informații auxiliare | ||
+ | *** care este directorul ''home'' al utilizatorului | ||
+ | *** shell-ul implicit al utilizatorului | ||
+ | |||
+ | === cat, tac, nl === | ||
+ | |||
+ | * Folosiți comanda ''cat'' pentru a afișa conținutul fișierului ''passwd''. | ||
+ | * Căutați în ''man'' un parametru astfel încât să numerotați linile din output. | ||
+ | ** Folosiți o metodă care numără inclusiv linile albe. | ||
+ | ** Folosiți o altă metodă care nu numerotează linile albe. | ||
+ | * Rulați comanda<code> | ||
+ | tac passwd | ||
+ | </code> | ||
+ | ** Ce observați? | ||
+ | * Rulați comanda<code> | ||
+ | nl passwd | ||
+ | </code> | ||
+ | ** Cu ce este echivalentă? (''cat'' + ce parametru?) | ||
+ | |||
+ | === head, tail === | ||
+ | |||
+ | * Rulați comanda<code> | ||
+ | head passwd | ||
+ | </code> | ||
+ | ** Ce afișează? | ||
+ | * Rulați comanda<code> | ||
+ | cat passwd | head | ||
+ | </code> | ||
+ | ** Ce afișează? | ||
+ | * Rulați comanda<code> | ||
+ | cat -n passwd | head | ||
+ | </code> | ||
+ | ** Ce afișează? | ||
+ | Vom folosi combinația ''cat -n'' și operatorul ''|'' (pipe) pentru a simplifica înțelegerea output-ului. | ||
+ | * Rulați comanda<code> | ||
+ | cat -n passwd | head -n 4 | ||
+ | </code> | ||
+ | ** Ce afișează? | ||
+ | * Rulați comanda<code> | ||
+ | cat -n passwd | head -n +4 | ||
+ | </code> | ||
+ | ** Ce afișează? | ||
+ | * Rulați comanda<code> | ||
+ | cat -n passwd | head -n -4 | ||
+ | </code> | ||
+ | ** Ce afișează? | ||
+ | * Rulați comanda<code> | ||
+ | cat -n passwd | tail | ||
+ | </code> | ||
+ | ** Ce afișează? | ||
+ | * Rulați comanda<code> | ||
+ | cat -n passwd | tail -n 4 | ||
+ | </code> | ||
+ | ** Ce afișează? | ||
+ | * Rulați comanda<code> | ||
+ | cat -n passwd | tail -n -4 | ||
+ | </code> | ||
+ | ** Ce afișează? | ||
+ | * Rulați comanda<code> | ||
+ | cat -n passwd | tail -n +4 | ||
+ | </code> | ||
+ | ** Ce afișează? | ||
+ | * Rulați comanda<code> | ||
+ | cat -n passwd | head -n 6 | tail -n 2 | ||
+ | </code> | ||
+ | ** Încercați să înțelegeți output-ul. | ||
+ | |||
+ | === sort, uniq === | ||
+ | |||
+ | * Rulați comanda<code> | ||
+ | cat passwd | sort | ||
+ | </code> | ||
+ | ** Ce observați? | ||
+ | * Căutați în ''man'' un parametru pentru ''sort'' astfel încât sortarea să se facă în ordine inversă. | ||
+ | * Rulați comanda<code> | ||
+ | cat passwd | uniq | ||
+ | </code> | ||
+ | ** Redirectați output-ul într-un fișier numit ''1st''. | ||
+ | * Rulați comanda<code> | ||
+ | cat passwd | sort | uniq | ||
+ | </code> | ||
+ | ** Redirectați output-ul într-un fișier numit ''2nd''. | ||
+ | Ce este diferit între 1st și 2nd? | ||
+ | * Folosiți comanda ''wc'' pentru a vedea câte linii are fiecare fișier. | ||
+ | ** Ce s-a întâmplat cu linile goale? | ||
+ | |||
+ | === cut, tr === | ||
+ | |||
+ | * Rulați comanda<code> | ||
+ | cat passwd | ||
+ | </code> | ||
+ | * Rulați comanda<code> | ||
+ | cat passwd | cut -d':' -f1 | ||
+ | </code> | ||
+ | ** Ce observați? | ||
+ | * Rulați comanda<code> | ||
+ | cat passwd | cut -d':' -f5 | ||
+ | </code> | ||
+ | ** Ce observați? | ||
+ | * Rulați comanda<code> | ||
+ | cat passwd | cut -d':' -f6 | ||
+ | </code> | ||
+ | ** Ce observați? | ||
+ | * Rulați comanda<code> | ||
+ | cat passwd | cut -d':' -f1,5,6 | ||
+ | </code> | ||
+ | ** Ce observați? | ||
+ | * Rulați comanda<code> | ||
+ | cat passwd | ||
+ | </code> | ||
+ | * Rulați comanda<code> | ||
+ | cat passwd | tr 'x' 'X' | ||
+ | </code> | ||
+ | ** Ce s-a întâmplat? | ||
+ | * Rulați comanda<code> | ||
+ | cat passwd | tr 'ieu' 'IEU' | ||
+ | </code> | ||
+ | ** Ce observați? | ||
+ | * Rulați comanda<code> | ||
+ | cat passwd | tr 'ieu' 'IE' | ||
+ | <?code> | ||
+ | ** Ce observați? | ||
+ | * Rulați comanda<code> | ||
+ | cat passwd | tr 'ieu' 'I' | ||
+ | </code> | ||
+ | ** Ce observați? | ||
+ | * Rulați comanda<code> | ||
+ | cat passwd | tr -d 'x' | ||
+ | </code> | ||
+ | ** Ce observați? | ||
+ | * Rulați comanda<code> | ||
+ | cat passwd | tr -d 'home' | ||
+ | </code> | ||
+ | ** Ce observați? | ||
+ | * Rulați comanda<code> | ||
+ | cat passwd | tr -s o | ||
+ | </code> | ||
+ | ** Ce observați? (ceva mai observabil pe prima linie prima linie) | ||
+ | |||
+ | === grep === | ||
+ | |||
+ | * Rulați comanda<code> | ||
+ | cat passwd | grep 'var' | ||
+ | </code> | ||
+ | ** Ce observați? | ||
+ | * Rulați comanda<code> | ||
+ | cat passwd | grep -v 'var' | ||
+ | </code> | ||
+ | ** Ce observați? | ||
+ | * Rulați comanda<code> | ||
+ | cat passwd | grep '^r' | ||
+ | </code> | ||
+ | ** Ce observați? | ||
+ | * Rulați comanda<code> | ||
+ | cat passwd | grep 'h$' | ||
+ | </code> | ||
+ | ** Ce observați? | ||
+ | * Rulați comanda<code> | ||
+ | cat passwd | grep '^i.*h$' | ||
+ | </code> | ||
+ | ** Ce observați? | ||
+ | * Rulați comanda<code> | ||
+ | cat passwd | grep ^[r,i] | ||
+ | </code> | ||
+ | ** Ce observați? | ||
+ | |||
+ | === sed === | ||
+ | |||
+ | **sed** este un **stream editor**. Cel mai bine cunoscut pentru funcția de search and replace. | ||
+ | |||
+ | <code> | ||
+ | sed 's/foo/bar/g' in_file > out_file | ||
+ | </code> | ||
+ | |||
+ | Se poate adăuga parametrul ''-i'' pentru editare "in place" a fișierului: | ||
+ | |||
+ | <code> | ||
+ | sed -i 's/foo/bar/g' in_file | ||
+ | </code> | ||
+ | |||
+ | Înlocuirea se poate face prin expresii regulate: | ||
+ | |||
+ | <code> | ||
+ | sed -i 's/\^first/First/g' file | ||
+ | sed -i 's/[0-9]/X/g' file | ||
+ | </code> | ||
+ | |||
+ | |||
+ | În general, sintaxa se referă la o adresă (linii selectate) și la o acțiune asupra acelor linii: | ||
+ | |||
+ | <code> | ||
+ | # Pentru fiecare linie din text, dacă este între linia 3 și 4, printeaza-o; ignoră restul liniilor | ||
+ | sed -n '3,4p' foo.txt | ||
+ | # Pentru fiecare linie din text, dacă este ultima linie, printeaza-o; ignoră restul liniilor | ||
+ | sed -n '$p' foo.txt | ||
+ | </code> | ||
+ | |||
+ | Se pot aplica mai multe acțiuni asupra unui fișier, folosind parametrul ''-e'' la fiecare acțiune: | ||
+ | |||
+ | <code> | ||
+ | # Șterge liniile 4 și 2. | ||
+ | sed -e '4d' -e '2d' file | ||
+ | </code> | ||
+ | |||
+ | === awk === | ||
+ | |||
+ | **awk** este un întreg limbaj de procesare a textului. | ||
+ | |||
+ | În general, folosește un fișier de script pentru acțiuni, cu sintaxa: | ||
+ | |||
+ | <code> | ||
+ | awk -f awk.script foo.file | ||
+ | </code> | ||
+ | |||
+ | |||
+ | Există un bloc de BEGIN, unul de END și corpul scriptului. | ||
+ | |||
+ | Exemplu de script: | ||
+ | |||
+ | <code> | ||
+ | |||
+ | # Begin Processing | ||
+ | BEGIN {print "Print Totals"} | ||
+ | |||
+ | # Body Processing | ||
+ | {total = $1 + $2 + $3} | ||
+ | {print $1 " + " $2 " + " $3 " = "total} | ||
+ | |||
+ | # End Processing | ||
+ | END {print "End Totals"} | ||
+ | |||
+ | </code> | ||
+ | |||
+ | Rezultate: | ||
+ | |||
+ | <code> | ||
+ | |||
+ | Input Output | ||
+ | 22 78 44 Print Totals | ||
+ | 66 31 70 22 +78 +44 =144 | ||
+ | 52 30 44 66 +31 +70 =167 | ||
+ | 88 31 66 52 +30 +44 =126 | ||
+ | 88 +31 +66 =185 | ||
+ | End Totals | ||
+ | |||
+ | </code> | ||
+ | |||
+ | Fiecare câmp dintr-o linie poate fi folosită ca o variabilă: | ||
+ | |||
+ | <code> | ||
+ | İnput | ||
+ | 1 clothing 3141 | ||
+ | 1 computers 9161 | ||
+ | 1 textbooks 21312 | ||
+ | 2 clothing 3252 | ||
+ | 2 computers 12321 | ||
+ | 2 supplies 2242 | ||
+ | 2 textbooks 15462 | ||
+ | </code> | ||
+ | |||
+ | <code> | ||
+ | |||
+ | awk 'if ($2 =="computers"){print}' sales.dat | ||
+ | |||
+ | </code> | ||
+ | |||
+ | <code> | ||
+ | Output | ||
+ | 1 computers 9161 | ||
+ | 2 computers 2321 | ||
+ | </code> | ||
+ | |||
+ | == Exerciții == | ||
+ | |||
+ | # Realizați un oneliner care parsează output-ul comenzii ''date'' și afișează un mesaj de forma ''Este ora X și Y minute''. | ||
+ | # Realizați un oneliner care afișează username-ul utilizatorilor reali din sistem. Considerăm un utilizator real, un utilizator al cărui director ''home'' are forma ''/home/USER''. (hint: ''/etc/passwd'') | ||
+ | # Realizați un oneliner care afișează numele fișierelor din ''/usr/include'' care includ antentul ''features.h''. | ||
+ | #* **Hint**: ''grep'', ''cut'' | ||
+ |