Филтри

Извор: ВикиЕТФ
(преусмерено са Филтери)

Филтери су програми које служе за обраду улаза и резултате те обраде штампа на стандардном излазу. Свеједно да ли желите да сортирате линије неког текстуалног фајла, да сазнате где се налази неки шаблон, избројите линије у вашем програму,... за све то и много више можете да користите филтере.

Садржај

Једноставнији филтери

Опција Опис
-l Штампа број линија
-w Штампа број речи
-c Број бајтова
$ wc -l /usr/include/stdio.h
838 stdio.h

Када му задамо фајлове као параметар штампа име фајла иза бројача.

$ wc -l /usr/include/*.h
246 /usr/include/aio.h
64 /usr/include/aliases.h
41 /usr/include/alloca.h
138 /usr/include/a.out.h
........................
42 /usr/include/xlocale.h
24847 total

Напомена: Скратио сам излаз команде због читљивости.

Такође ако задамо више фајлова "wc" ће на крају дати суму. Тако у претходној команди видимо да укупно имамо 24847 линија у свим фајловима заглавља у "/usr/inlude/" фолдеру.

$ cat /usr/include/stdio.h | wc -l
838

Овде видимо да "wc" броји линије са стандардног улаза ако јој не дамо фајлове.

Опција Опис
-b Игнорише водеће бланко знакове
-n Ради нумеричко сортирање, притом не преводећи знаковну репрезентацију у број
-r Обрнут редослед сортирања
-t Овом опцијом можете да специфирате свој симбол за растављање поља, уместо подразумеваног (транзиција са небланко на бланко знак)
-k Кључеви који се узимају у обзир приликом сортирања, подразумевано се узима читава линија
$ cat /etc/passwd|cut -d: -f1,3 |sort -t: -k2 -n
root:0
daemon:1
bin:2
sys:3
sync:4
games:5
man:6
lp:7
mail:8
news:9
uucp:10
proxy:13
www-data:33
...

Прво што радимо јесте да вадимо прво и треће поље помоћу "cut" програма. Касније уз помоћ "-t" опције кажемо који сепаратор желимо и специфирамо по којим пољима желимо да вршимо нумеричко сортирање.

$ cat .bash_history |tr -s "[:blank:]" | sed 's/[[:blank:]]*$//' | sort| uniq -c | sort -k1 -b -n -r | head
     10 ls
      4 cd ..
      3 info coreutils
      3 cd stanislav/
      2 sudo df -i
      2 ls -l
      2 lsb_release -a
      2 less /etc/fstab
      2 head passwd -n1 | sed 's/\n/:/' | tac -s:
      2 cd

На овај начин можемо да добијемо десет најкоришћенијих команди.

Опција Опис
-d Штампа само линије које су се понављале
-u Штампа само линије које су уникатне
-c Штампа број понављања у првој колони

-f1" само поље један, "-f1-2" од 1-2 поља, "-f1,4" штампа прво и четврто поље...).

Следећи пример штампа само име корисника и његов командно окружење.

$ cat /etc/passwd | cut -d: -f1,7
...
root:/bin/bash
daemon:/bin/sh
bin:/bin/sh
sys:/bin/sh
sync:/bin/sync
games:/bin/sh
man:/bin/sh
lp:/bin/sh
mail:/bin/sh
news:/bin/sh
uucp:/bin/sh
proxy:/bin/sh
www-data:/bin/sh
backup:/bin/sh
list:/bin/sh
irc:/bin/sh
gnats:/bin/sh
nobody:/bin/sh
libuuid:/bin/sh
syslog:/bin/false
klog:/bin/false
...

Пар примера "tr" команде:

$ echo "mala Velika slova" | tr "a-z" "A-Z"
MALA VELIKA SLOVA

Ово је пример транслирања знакова.

$ ls -l | tr -s "[:blank:]" | cut -d" " -f1,2,3,4 | head
total 7797
-rw-r----- 1 root adm
-rw-r----- 1 root adm
-rw-r----- 1 root adm
-rw-r----- 1 root adm
-rw-r----- 1 root adm
drwxr-x--- 2 root adm
drwxr-xr-x 2 root root
-rw-r----- 1 root adm
-rw-r----- 1 root adm


Овде користимо опцију "-s" (squash) која брише понављање одређеног знака или скупа знакова. Овде сам уместо размака ставио "Posix" ознаку бланко знака, више о овоме видите у одељку који се бави регуларним изразима (Регуларни изрази).

Сложенији филтери

Када нам је потребна комплекснија обрада стандардног улаза или фајлова користићемо програме попут "grep", "sed" и "gawk". За рад са сва три програма потребно је познавање регуларних израза па зато прво њих пролазимо.

Grep програм ћемо користити при филтерисању улаза и избацивању само нама битних линија, док ћемо "sed" користити за линијску обраду фајлова. "Gawk" у себи садржи програмски језик у себи и такође је послужио и као основа неких данас популарних језика као што је "Perl", и због своје флексибилности може да замењује оба претходно наведена програма.

Регуларни изрази

На Линуксу се користе основни и проширени регуларни изрази. Почећу тако што ћу описати проширену варијанту и рећи ћу које ствари се разликују у односу на основну варијанту. Иначе основни регуларни изрази постоје због компатибилности са старим програмима (нпр. "ed"), а углавном се сада користе проширена варијанта. Такође можете да користите регуларне изразе у разним програмским језицима што вам може олакшати решавање одређене класе проблема.

Проширени регуларни израз се састоји из једног или више гранања који су одвојени са "|" знаком. Свака грана се састоји из једног или више делова. Делови су уствари атоми који могу бити праћени са ознаком броја понављања. Постоје уобичајене ознаке понављања као што су "*" нула или више пута, "+" једанпут или више пута, "?" нула или једанпут и одређени опсег.

Опсези се одређују тако што се стављају у витичасте заграде "{}". Први број означава минималан број понављања а други максималан. Други мора бити већи од првог. Ако је други изостављен подразумева се неограничен број понављања, а ако је први изостављен онда је минимална вредност нула (нпр. "{1,3}" између један и три понављања).

Атом може бити било који специјалан знак који је избегнут уз помоћ "\" знака (спец. знакови "^.[$()|*+?{\"), обични знакови, групе одвојене са "()", класе знакова (види доле), ознаке почетка (^) и краја ($) реда, тачка "." (која замењује било који знак).

Класе знакова почињу и завршавају се унутар угластих заграда. Сви знакови унутар се третирају све могуће комбинације за један знак (атом). Овде можемо да користимо опсеге нпр. "[0-9]" поклапа цифре од 0 до 9.

Такође су неке класе знакова стандардизоване, као: alnum, digit, punct, alpha, graph, space, blank, lower, upper, cntrl, print, xdigit.

Проширени Основни Објашњење
Регуларни изрази
. . Мења било који знак.
[…] \[...\] Мења било који знак из наведеног скупа ([abc] мења знакове a, b и c).
[^…] \[^...\] Мења било који знак који није у скупу.
* * Мења претходни знак 0 или више пута.
+ \{1,\} Мења претходни знак један или више пута.
 ? \{0,1\} Мења претходни знак нула или једанпут.
{n} \{n\} Мења претходни карактер n пута.
{n,m} \{n,m\} Мења претходни карактер најмање n а највише m пута.
{n,} \{n,\} Мења претходни карактер n или више пута.
^ ^ Означава почетак реда.
$ $ Означава крај реда.
( ) \( \) Груписање. Корисно када желите да се понављања односе не на један него на групу карактера. Такође, користи се у изразима који раде замену за реферирање на део препознате секвенце.
не постоји Одваја гране у регуларном изразу, непостоји еквивалент у основним регуларним изразима.

Пример:

((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)

Овде поклапамо IPv4 адресе. Унутар прве групе имамо једну групу која се састоји од укупно три гране одвојене са усправним цртама и после те групе се поклапа тачка ("\." мора се избећи њено специјално значење). Прво гранање се односи на бројеве који почињу 25 и завршавају са са бројевима од нула до пет, пошто IP бројеви се крећу у опсегу од 0 до 255. Друго гранање се односи на бројеве који почињу само са двојком, а друга цифра може да се креће између 0 и 4, а задња наравно између 0 и 9. И последње треће гранање се односи на све остале случајеве, овде су прва и задња цифра опционе ("?" број понављања) а цифра између је обавезна, ово обезбеђује да увек постоји један број у подгрупи. Прва група се понавља три пута и затим следи иста таква група коју нећу објашњавати пошто је идентична.

grep

Grep претражује линије на стандардном улазу, или у фајловима које сте му задали, и штампа линије које садрже регуларни израз који сте му задали. У основи он ће претраживати фајлове које сте му дали или ће обрађивади стандардни улаз који сте му проследили са неке друге команде.

$ ps aux | grep "ime_programa$"'
1000     16504  3.7  8.0 181968 83888 ?        Sl   07:42   6:04 ime_programa

Подебљао сам израз који се поклапа са регуларним изразом, овде само користимо ознаку за крај линије $.

$ cat /etc/group | grep "^root:"
root:x:0:

$ cat /etc/group | grep "^root.*:"
root:x:0:

Последњи пример је један од битнијих зато што показује да регуларни израз поклапа највише што може. Морамо водити рачуна о томе када формираму регуларне изразе.

За почетак није лоше да користите опцију --color да би вам grep означио део који се поклапа са регуларним изразом.

Фајл /etc/group има у себи списак група које постоје на систему и припадајући корисници су излистани на крају.

$ cat /etc/group | grep ".*:.*user.*$"
adm:x:4:user
dialout:x:20:user
cdrom:x:24:haldaemon,user
floppy:x:25:haldaemon,user
audio:x:29:user

Овом командом листамо све групе којима припада корисник user.

Опција Опис
Корисне grep опције
-H, --with-filename Штампа и име фајла заједно са реченицом где је нашао шаблон.
-i, --ignore-case Игнорише величину слова.
-v, --invert-match Штампа линије које не садрже дати шаблон.
-n, --line-number Штампа и број линије.
$ grep /etc/passwd /etc/group -e "root"
/etc/passwd:root:x:0:0:root:/root:/bin/bash
/etc/group:root:x:0:
$ grep /etc/passwd /etc/group -e "root" -n
/etc/group:5:adm:x:4:user
/etc/group:15:dialout:x:20:user
/etc/group:18:cdrom:x:24:haldaemon,user
/etc/group:19:floppy:x:25:haldaemon,user
/etc/group:22:audio:x:29:user

SED

awk и sed су програми који се могу користити за разне трансформације над текстуалним подацима.

За пример употребе написаћемо кратку скрипту која прихвата текстуалну датотеку са именима студената и њиховим бројевима индекса, и креира им налоге на систему.

Улазна датотека има облик:

12121212        2005/1234       Stanko Stankovic
23123123        2005/1233       Petar Petrovic
12312313        2004/1212       Bane Brankovic

Где је прва колона будућа шифра корисника.

Прво ћемо искористити sed-ову команду s (енг. substitute), која ради замену ствари које је препознала у улазним подацима. Основни облик команде је s/trazeni-regularni-izraz/zamena/.

Дакле, треба да препознамо прву колону која садржи шифру, за то ће нам бити довољно [0-9]*. После тога следи један табулатор (\t), и онда година уписа.

Пошто желимо да у корисничком имену искористимо само задње две цифре године, препознаћемо све четири цифре, али ћемо заградама оградити само две тако да можемо да их искористимо касније ([0-9][0-9]\([0-9]*\)).

Следећа је коса црта, која нам није потребна, али треба да је препознамо (\/).

Даље следи број индекса који памтимо цео (\([0-9]*\)), и опет табулатор.

Следе име и презиме, али ми од тога желимо да запамтимо засебно иницијале, а такође желимо да имамо и цело име да би навели име корисника у коментару. Због тога правимо израз \(.\)\(.*\)\ \(.\)\(.*\).

Даље треба да формирамо замену.

Почињемо са нашом командом и фиксним параметрима (adduser -g pos - сви корисници ће припадати групи pos). Опцији -c треба да проследимо име и презиме. Ако у првом изразу погледамо редослед група (заграда), видећемо да је почетно слово имена у групи 4, остатак имена у групи 5, а почетно слово презимена и његов остатак у групама 6 и 7. Даље, по сличном принципу формирамо и корисничко име. За подешавање шифре корисника користимо прву групу коју прослеђујемо команди passwd.

Потребан је још само један ред да би спустили све ово у мала слова, и скрипта је готова.

#!/bin/bash
sed 's/\([0-9]*\)\t[0-9][0-9]\([0-9]*\)\/\([0-9]*\)\t\(.\)\(.*\)\ \(.\)\(.*\)/adduser -g pos -c \"\4\5 \6\7\" \4\6\3\2; echo \1 | passwd \4\6\3\2 --stdin/' |
sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/' # i prebaci u lowercase

Можете такође користити команду tr да бисте пребацили из великих у мала слова уместо дуге команде sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/', можемо написати tr 'A-Z' 'a-z'.

Ако желимо све ове команде да извршимо и додамо кориснике, можемо да преуследимо излаз задње sed команде у sh, који ће их секвенцијално извршити.

AWK

Awk се стандардно налази на рачунарима на *nix системом и служи за једноставне обраде текст фајлова у само пар линија кода. Можемо га посматрати као проширење grep команде са нумеричким и логичким конструкцијама. У почетку је развијан од стране Aho, Weinberger, и Kernighan-а, а касније је допуњен од стране Bell-а. Даљи развој је наставила GNU фондација под именом gawk, и највероватније имате ову верзију на својим рачунарима.

Можете да га користите на два начина:

cat fajl | gawk ‘(sablon){akcija}’
cat file | gawk -f program.awk

[program.awk]

#!/usr/bin/gawk –f
# Ovo je komentar
(sablon) {akcija}
…

Програмирање се ради тако што направите листу правила, а та правила се редом примењују на записе (records) или линије. Правила се састоје из шаблона и акције. Ако се запис поклапа са шаблоном онда се примењује акција на њега.

[Улаз]

PING google.navigation.opendns.com (208.69.34.230) 56(84) bytes of data.
64 bytes from google.navigation.opendns.com (208.69.34.230): icmp_seq=1 ttl=45 time=57.2 ms
64 bytes from google.navigation.opendns.com (208.69.34.230): icmp_seq=2 ttl=45 time=54.4 ms
64 bytes from google.navigation.opendns.com (208.69.34.230): icmp_seq=3 ttl=45 time=66.9 ms

--- google.navigation.opendns.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 54.453/59.525/66.919/5.347 ms

[Програм]

ping www.google.com | awk '(/icmp_seq/) {print $0}'

[Излаз]

64 bytes from google.navigation.opendns.com (208.69.34.230): icmp_seq=1 ttl=45 time=57.2 ms
64 bytes from google.navigation.opendns.com (208.69.34.230): icmp_seq=2 ttl=45 time=54.4 ms
64 bytes from google.navigation.opendns.com (208.69.34.230): icmp_seq=3 ttl=45 time=66.9 ms

Поља

Сваки запис је подељен на поља. Подразумевани раздвајач је празнина, шта наведемо у командној линији (-F) или вредност променљиве FS. Поља се нумеришу редом од јединице а нулто поље означава читав запис.

Улаз је исти. [Програм] Штампамо само поље 7.

ping www.google.com | awk '(/icmp_seq/) {print $7}'

[Излаз]

ttl=45
ttl=45
ttl=45

Променљиве

Променљивама у awk-у није потребна декларација, оне се аутоматски декларишу при употреби. Свака променљива је реалног и стринг типа у исто време. У зависности од употребе тумачимо вредности које се у њима налазе.

Име Опис
Често коришћене променљиве
FS Раздвајач поља.
NF Број поља у текућем запису.
NR Број записа у улазном фајлу.

Везе

Спољашње везе

Личне алатке
Именски простори
Варијанте
Акције
Навигација
Алатке