Hoppa yfir í efnið

Pípur og staðalstraumar

Verkefnasafn

Þessi kafli hefur tilheyrandi verkefnasafn á fylgiþjóninum. Til að sækja það og byrja að leysa verkefnin geturðu keyrt skipunina:

fetch pipes-and-standard-streams

Ein öflugasta hugmyndafræðin í Linux er sá möguleiki að geta miðlað gögnum á milli forrita. Í stað þess að vera með eitt risastórt forrit sem gerir allt getum við skeytt saman mörgum litlum forritum til að leysa flókin verkefni.

Staðalstraumar

Sérhvert forrit sem keyrir í Linux opnar sjálfkrafa þrjár samskiptarásir sem kallast staðalstraumar (e. standard streams), þ.e. staðalílag (e. standard input, oft stytt sem stdin), staðalfrálag (e. standard output, oft stytt sem stdout) og villufrálag (e. standard error, oft stytt sem stderr).

Staðalílagið er sá straumur þar sem forritið tekur á móti gögnum. Ef forritið er keyrt á hefðbundinn hátt kemur hann oftast frá lyklaborðinu.

Staðal- og villufrálög eru straumar þar sem forritið getur komið frá sér gögnum og skilaboðum. Ef forrit er keyrt á hefðbundin hátt enda skrifast bæði frálögin út á skjáinn. Algengast er að forrit skili frá sér gögnum á staðalfrálaginu og villumeldingum á villufrálaginu.

flowchart LR
    KB[Lyklaborð] -->|staðalílag| P((Forritið))
    P -->|staðalfrálag| OUT[Skjárinn: gögn]
    P -->|villufrálag| ERR[Skjárinn: villuskilaboð]

Af hverju tvö frálög?

Ef forrit á að skila gögnum viljum við ekki endilega blanda villumeldingum saman við gögnin. Villumeldingar þýða ekki endilega að forritið hafi hrunið eða keyrsla þess hafi misheppnast. Oft gefa forrit frá sér viðvaranir eða önnur skilaboð sem upplýsingar til notanda. Með því að hafa sérstakt villufrálag (stderr) getum við vísað gögnum og villuskilaboðum á mismunandi staði.

Með því að keyra skipunina

find /root
sjáum við tvær línur birtast, þ.e.

/root
find: ‘/root’: Permission denied

Villuskilaboðin segja okkur að við höfum ekki réttindi til að skoða heimamöppu ofurpaursins, /root. Fyrsta línan gefur okkur þó þá möppu sem við vitum að er til staðar, og við höfum aðgang til að sjá, sem er /root.Þó að þessar línur skrifist báðar út í skelina, eiga þær uppruna sinn úr sitt hvorum straumnum og Linux heldur utan um það.


Endurvísun

Við hefðbundna keyrslu kemur ílag, alla jafna, frá lyklaborði og frálag er skrifað á skjá. Með endurvísun (e. redirection) er hægt að breyta því, þannig að ílag komi frá skrá eða frálag skrifist í skrá.

Frálag í skrá

Það er ekki alltaf möguleiki að vinna og lesa gögn af skjá. Stundum viljum við geyma gögn til að vinna með þau seinna og stundum er einfaldlega of mikið af gögnum til að hægt sé að meðhöndla þau eða lesa beint af skjá.

Staðalfrálag

Skelin býður, þess vegna, upp á nokkrar aðferðir til að beina frálagi í skrár. Í því tilfelli, í stað þess að frálagið sé prentað á skjáinn, er það skrifað í skrá. Virkjarnir > og >> segja skelinni að staðalfrálagið eigi að skrifast í skrá. Munurinn á þessum tveimur virkjum er að með > er skráin alltaf yfirskrifuð, þannig tapast öll gögn sem í henni voru fyrir. Með >> er úttakinu bætt aftast í skránna.

Eftirfarandi skipanir sýna muninn á virkjunum tveimur.

ls > ls1.txt          # býr til nýja skrá ls1.txt með staðalúttaki
cat ls1.txt
ls /dev > ls1.txt     # yfirskrifar ls1.txt með nýju staðalúttaki
cat ls1.txt
ls >> ls2.txt         # býr til nýja skrá ls2.txt
cat ls2.txt
ls /dev >> ls2.txt    # bætir nýju úttaki aftast í ls2.txt
cat ls2.txt

Misræmi í úttaki

Glöggir lesendur taka eflaust eftir því að innihaldið í ls1.txt lítur ekki eins út og þegar ls er keyrt beint inni í skelinni.

Þegar ls (án stillinga) er keyrt í skelinni er úttakinu skipt í dálka, til að fækka línum í úttakinu. Þannig gæti úttakið verið

challenges  examples  README.txt

þegar ls er keyrt beint í skelinni, en verið

challenges
examples
README.txt

í ls1.txt. Grundvallarástæða þess að misræmi er þarna á milli er að skipanir geta greint hvort að staðalúttakið sé að fara beint út í skelina eða hvort það sé að fara eitthvert annað eins og í skrá. Mörg innbyggð forrit, sérstaklega þau sem skrifa úttak með litum og öðru þægilegu viðmóti, breyta hegðun sinni þegar staðalúttakið fer ekki í skeilina. Ástæða þess er að, þegar úttakið fer annað en í skel, er líklega verið að vinna frekar með gögnin og þá getur verið óhentugt að hafa gögnin á formi sem erfiðara er að þátta (e. parse). Við lærum meira um þetta seinna í kaflanum.

Skoðum annað dæmi,

find /root > root.txt
Hér sjáum við villuskilaboð skrifast út á skjáinn á meðan staðalfrálagið er skrifað í root.txt. Hér sjáum við hvernig skelin greinarmun á þessum frálögum.

Villufrálag

Til að endurvísa villufrálaginu í skrá er hægt að notast við virkjana 2> og 2>> og er hegðun þeirra nákvæmlega eins og endurvísunarvirkja staðalfrálagsins. Hægt er að blanda endurvísunarvirkjunum saman. Ef við keyrum

find /root > root.txt 2>> root-err.txt
skrifast staðalfrálagið í root.txt, en villufrálagið bætist aftan við root-err.txt.

Sameining frálaga

Ef við kjósum að beina bæði venjulegu frálagi og villuboðum á sama staðinn getum við notast við skipun á borð við

skipun > allt.txt 2>&1
Fyrri virkinn segir að staðalfrálag (stdout) eigi að skrifast í allt.txt. Seinni virkinn, 2>&1, segir að villufrálag (táknað með 2) eigi að skrifa á sama stað og staðalfrálagið (táknað með 1). Hér skiptir röðin miklu máli því við skilgreinum fyrst hvert venjulegt frálag fer og tengjum villufrálagið svo við þá slóð.

Skráarlýsingar

Eins og rætt var í kaflanum um skráakerfið, þá lítur Linux á allt sem skrár. Það sama gildir um staðalstraumana þrjá; á bak við tjöldin eru þeir einfaldlega opnar skrár sem fá úthlutað sínum eigin skráarlýsingum (e. file descriptors):

  • 0 er staðalílag (stdin).
  • 1 er staðalfrálag (stdout).
  • 2 er villufrálag (stderr).

Tölurnar sem við höfum verið að nota með endurvísunarvirkjunum vísa beint í þessa skráarlýsinga! Við gætum allt eins skrifað 1> allt.txt, en af því að það er svo algengt að beina staðalfrálagi þá gerir skelin ráð fyrir því að við meinum 1 ef engin tala er gefin upp fyrir framan virkjann.

En hvað með og-merkið & í 2>&1? Það vísar til þess að talan á eftir því sé skráarlýsingur (straumur), en ekki venjuleg skrá í skráakerfinu. Þannig þýðir 2>&1 að við ætlum að beina villufrálagi í staðalfrálag, á meðan 2>1 myndi einfaldlega þýða að villufrálagið skrifast í nýja skrá sem heitir bókstaflega 1.

Ílag úr skrá

Á sama hátt og hægt er að skrifa frálag í skrár er einnig hægt að lesa ílag úr skrá, en það er gert með virkjanum <. Þegar honum er beitt, hættir skelin að taka við ílaginu frá lyklaborðinu og skrifar, þess í stað, innihald skráarinnar í ílagið. Ef við heimsækjum ~/examples/data og keyrum

wc -l < names.txt

Notkun ílagsvirkjans er sjaldgæfari en frálagsvirkjanna þar sem flest forrit bjóða upp á að taka við skrám, sem á að lesa, sem viðföng. Til dæmis fæst sama niðurstaða þegar

grep a < names.txt
og
grep a names.txt
eru keyrðar. Í fyrra tilfellinu les grep gögnin af staðalílaginu, og skelin sér svo um að setja innihald names.txt í staðalílagið. Í seinna tilfellinu afhendum við grep nafnið á skránni sem á að lesa, og forritið sjálft opnar skránna og les innihaldið. Það er því tæknilegur munur á keyrslunum, en enginn munur á niðurstöðunum. Í fyrri kvaðningunni, til dæmis, veit grep ekki nafnið á skránni sem verið er að vinna með, en þær upplýsingar liggja fyrir í seinni kvaðningunni.

Svartholið

Ef við viljum hunsa frálag eða villuboð sem við höfum engan áhuga á býður Linux upp á sérstaka skrá /dev/null. Hún er þeim eiginleikum gædd að allt sem er skrifað í hana er hunsað og endar því ekki í skráakerfinu.

Algengt er að nota þetta til að hunsa staðalfrálagið eða villufrálagið, þannig það prentist ekki út á skjáinn. Ef við höfum bara áhuga á villufrálaginu, og viljum hunsa allt annað getum við, til dæmis, keyrt

find /root > /dev/null
Staðalfrálagið er þá ekki skrifað út og við sjáum aðeins villufrálagið. Að sama skapi, viljum við hunsa villufrálagið getum við keyrt
find /root 2> /dev/null

Prófaðu: vista frálag

Vistaðu raðaðan lista af nöfnum í playground/sorted-names.txt og bættu svo línufjölda aftan við sömu skrá.

Lausn

Við getum notað endurvísun og fylgt þessum skrefum

sort data/names.txt > playground/sorted-names.txt
wc -l data/names.txt >> playground/sorted-names.txt
cat playground/sorted-names.txt
sem býr fyrst til skrána og bætir svo línufjöldanum aftan við.

Prófaðu: aðskilja villur og frálag

Láttu ls reyna að sýna eina skrá sem er til og eina sem er ekki til. Vistaðu venjulegt frálag og villur í sitthvora skrána.

Lausn

Til þess að aðskilja staðalfrálag og villufrálag getum við keyrt skipunina

ls welcome.txt engin-svona-skra.txt > playground/ut.txt 2> playground/villur.txt
cat playground/ut.txt
cat playground/villur.txt
sem sýnir okkur vel hvernig straumarnir tveir vistast í sitthvorri skránni.


Pípur

Mörg Linux-forrit fylgja þeirri hefð að ef skrá er gefin sem viðfang þá vinnur forritið með gögnin úr henni, en ef ekkert viðfang er gefið eru gögnin lesin úr staðalílagi.

Við getum prófað þetta, t.d., með því að keyra skipunina

grep a
Við sjáum þá að skipunin lýkur sér ekki af, heldur bíður eftir inntaki frá okkur (þ.e., af staðalílagi). Ef við sláum inn texta sem inniheldur bókstafinn a og ýtum svo á Enter, sjáum við að línan er skrifuð aftur út og allir a-stafirnir eru merktir með öðrum lit. Ef við sláum inn texta sem inniheldur ekki a og ýtum á Enter, skrifast ekkert út. Til að segja skelinni að við séum búin að slá allt inn sem við viljum notum við Ctrl+D.

Þessi eiginleiki forrita að vinna á gögnum í gegnum staðalinntak er gríðalerga öflugur þegar kemur að vinnslu gagna og er forsenda hugmyndafræðinnar sem flest Linux forrit aðhyllast, þ.e. að gera einn hlut og gera hann vel.

Flæði gagna

Pípan | er virki sem tengir staðalfrálag einnar skipunar beint við staðalílag annarrar. Þessi virki gerir okkur kleift að nota eina skipun til að vinna eða framkalla gögn á einn hátt, svo aðra til að vinna með þá niðurstöðu, svo enn annað forrit til að vinna með þá niðurstöðu, og svo koll af kolli.

Segjum sem svo að við viljum vita hversu margar skrár og möppur eru í vinnumöppunni. Við vitum að ls gefur okkur lista af öllum möppum og skrám og að wc -l telur fjölda lína. Ef við gefum wc -l úttakið úr ls sem staðalílag, þ.e.

ls | wc -l
mun það einmitt telja fjölda mappa og skráa í vinnumöppuni.

Á sama hátt getum við fundið allar skrár eða möppur undir vinnumöppunni, þar sem full slóð á skránna inniheldur a, með

find -type f | grep -i a | wc -l
Hér byrjum við á að finna allar skrár undir vinnumöppunni með find -type f, sem prentar hverja skrá fyrir sig, línu fyrir linu. Úttakið úr þeirri skipun er svo sett inn í grep -i a sem leitar að bókstafnum a, hvort sem hann er há- eða lágstafur, í úttakinu og prentar aðeins út þær línur sem innihalda hann. Úttakið úr þeirri skipun samanstendur því aðeins að slóðum skráa sem innihalda a, og mun wc -l þannig telja fjölda þeirra.

Oft má sleppa cat

cat skrá.txt | grep orð virkar, en grep orð skrá.txt er einfaldara. cat er samt stundum gagnlegt þegar við erum að hugsa um pípuna sem færiband.

Ekki öll forrit fylgja hefðinni fullkomlega

Mörg textavinnslutól gera þetta, t.d. sort, grep, wc, sed og awk. Sum forrit þurfa samt alltaf skráarnafn eða nota aðra hegðun. Ef þú ert óviss er best að skoða --help eða man.

Prófaðu: sömu gögn, tvær leiðir

Notaðu sort og wc -l bæði með skráarnafni og með pípu.

Lausn

Við getum framkvæmt þetta á tvo vegu með því að keyra skipanirnar

sort data/names.txt
cat data/names.txt | sort

wc -l data/names.txt
cat data/names.txt | wc -l
sem sýnir hvernig pípur geta leyst sama verkefni og bein skráarvinnsla.

Verkefnayfirferð

Þá höfum við útskýringuna á því af hverju við bætum | check fyrir aftan skipanir í verkefnum þar sem beðið er um að skrifa lausnina út. Þá er staðalfrálaginu beint inn í skipunina check sem skrifar úttakið í skránna answer.txt og ber hana saman við rétt úttak.


Litir og pípur

Eins og minnst var á hér að ofan, geta forrit greint hvort staðalfrálagið þeirra fari beint í skeljagluggann eða áfram í pípu eða skrá. Þegar frálagið fer beint á skjáinn er oft gagnlegt að nota liti, en þegar frálagið fer í pípu geta litir verið til vandræða þar sem litir í skelinni eru framkallaðir með því að bæta sérstökum bætarunum, svokölluðum stýritáknum, inni í textanum.

Flest forrit slökkva sjálfkrafa á litum þegar þau sjá að frálagið fer ekki beint á skjá, sem við getum sannreynt með því að keyra

ls --color=auto
ls --color=auto | cat
þar sem fyrri skipunin sýnir litaðar skrár en sú seinni skilar venjulegum texta vegna þess að frálagið fer í gegnum cat.

Sama á við þegar við keyrum skipanir á borð við

grep --color=auto "root" /etc/passwd
grep --color=auto "root" /etc/passwd | cat
þar sem litunin á leitarorðinu hverfur oft í seinna skiptið þegar gögnum er pípað áfram.

Þvingaðir litir

Sum forrit leyfa þér að stjórna þessu, t.d. með --color=always, --color=auto eða --color=never. Ef þú notar --color=always í pípu geta litakóðarnir ferðast áfram og stundum ruglað önnur forrit sem eiga að vinna með hreinan texta.

Í sumum tilfellum kunna forrit sem pípað er inn í að meðhöndla liti og í því tilfelli er yfirleitt hægt að stilla forrit til að þvinga liti. Þetta á, til dæmis, við um síðufletta.

Ein þægileg leið til að fá yfirlit yfir möppu er að nota tree. Ef mappan inniheldur margar möppur og skrár getur það verið erfitt að skruna í gegnum úttakið og þá er hentugt að nota síðufletti, þ.e.

tree | less
Það gerir okkur auðveldar að fletta á milli og leita að skrám en við missum litina, þrátt fyrir að less kunni að meðhöndla liti. Við getum þá þvingað tree til að nota liti með stillingunni ⁻C, þ.e.
tree -C | less


Algeng tól í pípum

Algengt er að nota pípur til að meðhöndla, sía og umbreyta texta. Margar skipanir eru í boði sem vinna með texta og förum við hér yfir þær algengustu. Allar þessar skipanir fylgja þeirri hefð að inntakið er ýmist gefið sem viðfang eða á staðalílagi.

Röðun

Skipunin sort raðar línum inntaks í stafrófsröð.

Algengar stillingar

Stilling Lýsing
-r, --reverse Línum er raðað í öfuga stafrófsröð
-n, --numeric-sort Línum er raðað eftir tölugildi, sjá dæmi að neðan
-h, --human-numeric-sort Línum er raðað eftir tölugildum m.t.t. eininga, sjá dæmi að neðan

Dæmi

Hægt er að raða innihaldi skráa í stafrófsröð með

sort names.txt

Til að raða öllum möppum og undirmöppum í stærðarröð getum við prófað

du | sort 
en þá tökum við eftir að möppurnar birtast ekki í stærðarröð. Við gætum, til dæmis, séð möppu af stærð 4 koma á undan möppu af stærð 52. Ástða þess er að sort raðar í stafrófsröð og þar sem 4 er framar í stafrófinu, þá birtist hún á undan öllum tölum sem byrja á 5, hvort sem þær eru stærri eða ekki. Til að raða í talnaröð notum við
du | sort -n

Það getur þó reynst tormelt að lesa alltaf stærðir í bætum, og þess vegna býður du upp á stillinguna -h sem gefur stærðir í KB, MB, o.s.frv. til að auðvelda lesturinn. Hægt er að segja sort að raða eftir slíkum stærðum með einingum, þannig gefur

du -h | sort -h
okkur allar möppur í stærðarröð með þægilegri framsetningu á stærðum.

Að sía út endurtekningar

Skipunin uniq fjarlægir runur endurtekinna lína úr inntaki. um við fjarlægt allar endurtekningar sem birtast í

Algengar stillingar

Stilling Lýsing
-c, --count Skrifar út hversu oft hver lína birtist í inntakinu

Dæmi

Það er mikilvægt að hafa í huga að uniq fjarlægir ekki að allar endurtekningar, heldur bara þær sem birtast í runu. Ef innihald prufa.txt er eftirfarandi,

b
b
b
a
a
a
c
a
a
b
b
myndi
uniq prufa.txt
skila
b
a
c
a
b
þannig að allar línur sem eru endurteknar í röð eru fjarlægðar. Við athugum þó að ef inntakið er raðað þegar það kemur inn í uniq, þá munu allar endurtekningar náttúrulega koma í runu og þannig allar verða fjarlægðar. Þess vegna er uniq mjög oft notað samhliða sort. Þannig getum við fjarlægt allar endurtekningar úr prufa.txt með
sort prufa.txt | uniq
og endum við þá með
a
b
c

Skipunin

find -type f -exec basename {} \; | sort | uniq -c | sort -n
finnur hversu margar skrár bera hvert nafn. Skipunin basename sem tekur viðfang sem er slóð og skilar nafni þess sem slóðin vísar á, hvort sem það er mappa eða skrá, þ.e. textann sem er fyrir aftan aftasta skástrikið. Henni er beitt á allar skrár með -exec og skilar find þannig óröðuðum lista af öllum skráanöfnum. Fyrsta sort passar að skráanöfnin séu í röð svo að uniq geti talið og fjarlægt allar endurtekningar. Seinna sort raðar svo skránum eftir fjölda.

Klippa eftir dálkum

Skipunin cut „klippir“ ákveðna hluta úr hverri línu. Hún hentar vel þegar línur hafa einfalt og reglulegt snið, til dæmis þegar tvípunktur eða komma skilja að hluta lína.

Algengar stillingar

Stilling Lýsing
-d, --delimiter Afmarkari sem er notað til að aðskilja hluta lína
-f, --fields Hvaða dálka á að klippa út úr inntakinu
-c, --characters Segir hvaða stafi á að sækja úr hverri línu, í stað þess að nota afmarkara og dálka

Dæmi

Skráin /etc/passwd, sem inniheldur lista yfir alla notendur á Linux kerfum ásamt ýmsum upplýsingum um þá, notar tvípunkt sem afmarkara. Prófaðu fyrst að skoða innhald hennar með cat. Til að sækja bara fyrsta dálkinn, þ.e.a.s. gildið sem kemur á undan fyrsta tvípunktinum getum við keyrt

cut -d: -f1 /etc/passwd
Stillingin -d: velur tvípunkt sem afmarkara (e. delimiter) og -f1 velur fyrsta dálkinn (e. field). Við getum valið fleiri dálka eða bil dálka með
cut -d: -f1,7 /etc/passwd       # fyrsti og sjöundi dálkur
cut -d, -f1-3 data/scores.csv   # dálkur eitt til þrjú

Einnig getur cut valið stafi eftir staðsetningu þeirra í hverri línu fyrir sig, þannig ef við keyrum

echo "abcdefgh" | cut -c1-4
fáum við
abcd

cut er ekki fullkominn CSV-lesari

cut skilur ekki gæsalappir, kommur inni í reitum eða línuskipti inni í CSV-gildi. Fyrir einföld kennslugögn dugar það vel, en flóknara CSV lesum við með sérhæfðu tóli eða csv-safni Python.

Prófaðu: veldu dálka með cut

Sýndu aðeins nöfn og stig úr data/scores.csv. Nafnið er fyrsti dálkur og stigin sá þriðji.

Lausn
cut -d, -f1,3 data/scores.csv

Hauslínan fylgir með. Við sleppum henni með því að setja tail fremst:

tail -n +2 data/scores.csv | cut -d, -f1,3

Breyting stafa

Skipunin tr (stytting á translate) er notuð til að framkvæma ákveðnar breytingar á stöfum úr inntaki.

Algengar stillingar

Stilling Lýsing
-d, --delete Eyðir stöfum í stað þess að skipta þeim út
-s, --squeeze-repeats Þjappar saman endurteknum stöfum
-c, --characters Segir hvaða stafi á að sækja úr hverri línu, í stað þess að nota afmarkara og dálka

Dæmi

Skipunin tekur við tveimur viðföngum sem eru bæði túlkuð sem listi tákna, og er þá fyrsta tákninu í fyrri listanum breytt í fyrsta tákn seinni listans, og svo koll af kolli. Flest tákn sem gefin eru sem viðföng eru túlkuð sem þau sjálf, þ.e. a þýðir bara bókstafurinn a, en sumir strengir hafa ákveðna merkingu. Dæmi um það er t.d. [:lower:] og [:upper:] sem tákna alla há- og lágstafi í enska stafrófinu.

Við getum þannig breytt öllum (enskum) lágstöfum í hástafi með

echo "Hello there" | tr '[:lower:]' '[:upper:]'
og breytt kommum í línubil með
echo "a,b,c" | tr ',' '\n'

Með -d getum við eytt stöfum sem við höfum ekki áhuga á eins og bandstrikum í símanumerum

echo "Sími: 555-1234" | tr -d ' -'
og með -s getum við þjappað saman endurteknum stöfum, eins og t.d. endurteknum bilum sem mörg forrit skila frá sér
echo "anna     42      blár" | tr -s ' '

Stafir ekki orð

Athugum að tr 'köttur' 'hundur' skiptir ekki heila orðinu köttur út fyrir hundur, heldur skiptir k út fyrir h, ö fyrir u, o.s.frv. Skipunin varpar einstökum stöfum milli tveggja lista. Til að skipta út orðum eða mynstrum getum við notað sed.

Prófaðu: ein færsla í hverri línu

Láttu litina í rautt,grænt,blátt birtast hvern í sinni línu.

Lausn
echo 'rautt,grænt,blátt' | tr ',' '\n'

Breyting texta

Skipunin sed (stytting á stream editor) les texta línu fyrir línu, framkvæmir umbreytingar á textanum samkvæmt forskrift og skrifar niðurstöðuna. Sé sed gefið viðfang breytist upprunalega skráin ekki nema við biðjum sérstaklega um það.

Algengar stillingar

Stilling Lýsing
-i, --in-place Framkvæmir breytingar á skrám sem gefin eru sem viðföng. Getur einnig gert afrit af upprunalegu skránni til að tapa ekki gögnum.

Dæmi

Fyrsta viðfang sed er svokölluð skrifta (e. script) sem lýsir þeim breytingum sem á að framkvæma. Við ætlum ekki að kafa djúpt ofan í það skriftumál sem sed notar, enda á miklu að taka, en förum aðeins yfir algengustu aðgerðir.

Ein algengasta notkun á sed er til að skipta út einum streng fyrir annan, og er það gert með skipun sem hefur sniðið

s/[mynstur]/[nýr]/[stillingar]
sem segir sed að skipta út strengnum sem mátast við [mynstur] með strengnum [nýr], eins og t.d.
echo "Halló heimur" | sed 's/heimur/Linux/'

Sjálfgefin stilling sed er að skipta aðeins út fyrstu samsvörun hverrar línu, þannig ef margir hlutar línu mátast við mynstrið er aðeins þeim fyrsta skipt út, eins og sjá má með

echo "blár blár blár" | sed 's/blár/rauður/'
Með stillingunni g getum við sagt sed að skipta út öllum tilvikum sem mátast við mynstrið
echo "blár blár blár" | sed 's/blár/rauður/g'

Einnig er hægt að eyða út línum með sed með stillingunni d (þá er enginn skiptistrengur gefinn),

sed '/ INFO /d' logs/error.log
en athugið að hér er skránni logs/error.log ekki breytt, heldur er umbreytta útgáfan skrifuð út á staðalfrálagið. Viljum við breyta skránni getum við notað -i, þ.e.
sed -i.bak '/ INFO /d' logs/error.log
en þá er mikilvægt að hafa í huga að við getum misst gögn! Ef stillingin -i er gefin með viðfangi, eins og hér að ofan -i.bak, þá tekur sed fyrst afrit af skránni áður en hún er yfirskrifuð, þannig engin gögn hverfa. Ef -i hefur ekkert viðfang, þá er ekkert afrit tekið.

Gættu þín á sed -i

Stillingin -i breytir skránni sjálfri. Góð vinnuregla er að prófa fyrst án hennar og skoðaðu frálagið.

Prófaðu: hreinsaðu texta með sed

Sýndu logs/error.log þannig að orðið ERROR verði VILLA í frálaginu án þess að breyta upprunalegu skránni.

Lausn
sed 's/ERROR/VILLA/g' logs/error.log

Öflug textavinnsla

Þær skipanir sem við höfum séð hingað til eru hannaðar með afmarkaðar breytingar í huga, eins og að raða í stafrófsröð, skipta út staf eða orði. Ef að vinnsla gagna er orðin það flókin að ekkert þessara tóla dugir, er mögulega kominn tími til að draga fram skipunina awk (nefnd eftir höfundum sínum Aho, Weinberger og Kernighan). AWK er forritunarmál, sem skipunin notar til að umbreyta og skrifa út texta.

Við munum ekki kafa djúpt í forritunarmálið sjálft hér, heldur einblína á nokkrar „algengar uppskriftir“. Grunnbygging hvers awk forrits er mjög einföld:

mynstur { aðgerð }
Fyrir hverja línu í inntakinu athugar awk hvort hún passi við mynstur (e. pattern) og ef svo er framkvæmir það aðgerð (e. action). Ef mynstur er sleppt er aðgerðin framkvæmd á allar línur. Ef aðgerð er sleppt prentar awk einfaldlega alla línuna út (sjálfgefin aðgerð er {print $0}).

Skipunin awk hentar gríðarlega vel til að þátta (e. parse) dálka, endurraða þeim og skrifa þá út að nýju.

Algengar stillingar

Stilling Lýsing
-F Afmarkari (e. delimiter) sem er notaður til að aðskilja dálka

Dæmi

Sjálfgefið gerir awk ráð fyrir að dálkar séu aðskildir með bili eða inndrætti (e. tab). Við getum vísað í einstaka dálka í hverri línu með $ á eftirfylgt með númeri dálksins, þar sem $1 er fyrsti dálkur, $2 er annar, o.s.frv. Til að vísa í alla línuna (öll gögnin) notum við $0.

Ef við höfum inntak með mörgum dálkum, en höfum aðeins áhuga á að prenta þá út í annarri röð, getum við víxlað þeim. Hér sleppum við mynstrinu (svo þetta á við allar línur) og snúum við orðunum „Hæ heimur“:

echo "Hæ heimur" | awk '{print $2, $1}'

Ef við viljum vinna með gögn sem nota annan afmarkara, til dæmis tvípunkt, þá notum við stillinguna -F. Eins og við sáum áður aðskilur skráin /etc/passwd dálka með tvípunkti. Við getum prentað út fyrsta dálkinn (notandanafn) á eftirfarandi hátt:

awk -F ':' '{print $1}' /etc/passwd

Munurinn á cut og awk sést vel þegar við viljum blanda saman dálkum úr inntakinu og okkar eigin texta. Hér sækjum við notandanafn (dálkur 1) og slóð að skel (dálkur 7) og tengjum saman í eina setningu:

awk -F ':' '{print "Notandinn " $1 " notar skelina " $7}' /etc/passwd

Auk þess að prenta út og endurraða dálkum er awk frábært til að sía gögn með því að nýta sér mynstrið. Í eftirfarandi dæmi viljum við aðeins línur þar sem fyrsti dálkur er stærri en 100. Þar sem við skilgreinum enga { aðgerð } blokk þá framkvæmir awk sjálfgefnu aðgerðina sem er {print $0} (prenta alla línuna út).

echo -e "50 epli\n150 appelsínur\n20 bananar" | awk '$1 > 100'

Samantekt

Skipun Hlutverk
sort Raðar línum
uniq Fjarlægir og telur endurteknar línur
wc Telur línur, orð og bæti
cut Klippir út dálka eða stafi
tr Skiptir út eða eyðir stöfum
sed Breytir textastraumi línu fyrir línu
awk Vinnur með dálka og mynstur
tee Skrifar bæði á skjá og í skrá
xargs Breytir línum úr ílagi í viðföng fyrir skipun

Listi sem viðfang

Við höfum séð hversu öflug pípan getur verið í vinnslu og meðhöndlun gagna, en eitt tilfelli sem pípan getur ekki leyst er þegar úttakið úr einu forriti þarf að enda sem viðfang í það næsta. Segjum sem svo að við viljum finna allar .md skrár í vinnumöppunni og finna hversu margar línur þær innihalda, hver um sig.

Við vitum að hægt er að nota

find -name "*.md"
til að finna skrárnar, en ef pípum niðurstöðunni í wc, þ.e.
find -name "*.md" | wc -l
mun það aðeins skila fjölda skráa sem fundust en ekki fjölda lína í hverri fyrir sig. Til að finna það, þyrftum við að kalla á wc -l [skrá1] [skrá2] [skrá3] .... Þetta er nákvæmlega það sem skipunin xargs (stytting á extended arguments) leyfir okkur að gera. Hún tekur skipun sem viðfang, les inn allar línur af staðalílagi sem viðföng og kallar svo á skipunina með þeim viðföngum. Til að finna fjölda lína í .md skrám getum við þannig keyrt,
find . -name "*.md" | xargs wc -l
þar sem find finnur skrárnar og xargs setur þær allar sem viðföng í kvaðningu wc sem sér um línutalninguna.

Bil í slóðum

Ef slóðir innihalda bil mun xargs ekki virka sem skyldi, þar sem bilið er túlkað sem upphafið á nýju viðfangi. Margar Linux skipanir bjóða upp á að skrifa núllbæti á milli gilda í stað línubils, og með find má gera það með -print0. Svo skemmtilega vill til að xargs styður það einnig að skipta viðföngum upp eftir núllbætum, með stillingunni -0. Við getum þannig notað þetta saman

find -name "*.txt" -print0 | xargs -0 wc -l
til að tryggja að skráarnöfn með bilum eða sértáknum valdi ekki vandamálum.

Of mörg viðföng

Flestar skeljar hafa takmörk á lengd skipana. Það getur því gerst að xargs smíði skipun með of mörgum viðföngum þannig að skelin ráði ekki við það.

Að kljúfa strauminn

Skipunin tee (dregið af T-stykki í pípulögnum) virkar eins og T-stykki í vatnslögn þannig að frálagið fer bæði á skjá og í tilgreinda skrá. Ef við prófum að keyra

cut -d, -f1 data/scores.csv | tee playground/names-from-csv.txt
sjáum prentast fyrsti dálkur scores.csv út á skjáinn, en er einnig vistaður í playground/names-from-csv.txt.


Dæmi: Greining textaskrár

Segjum að við séum með logs/access.log skrá með mörgum línum og markmið okkar sé að finna þær 5 IP-tölur sem koma oftast fyrir í fyrsta dálki skráarinnar. Til þess getum við skeytt saman mörgum tólum og keyrt flókna keðju á borð við

cut -d' ' -f1 logs/access.log | sort | uniq -c | sort -nr | head -n 5
sem leysir verkefnið á örfáum sekúndum.

Í þessari skipun fylgjum við þessum skrefum:

  1. cut -d' ' -f1: klippir út fyrsta dálkinn þar sem IP-talan er að finna.
  2. sort: raðar öllum línum saman svo hægt sé að telja þær.
  3. uniq -c: telur nákvæmlega hve oft hver IP-tala kemur fyrir.
  4. sort -nr: raðar niðurstöðunum tölulega þannig að stærsta talan komi fyrst.
  5. head -n 5: síar út og sýnir okkur einungis efstu 5 línurnar.

Prófaðu sjálf/ur

Hvernig myndirðu telja hversu margar einstakar línur eru í data/names.txt?

Ein lausn

Við getum raðað og eytt endurtekningum áður en við teljum með því að keyra

sort data/names.txt | uniq | wc -l
sem skilar okkur nákvæmum fjölda einstakra nafna.

Prófaðu: algengasti liturinn

Hvaða litur kemur oftast fyrir í data/colors.txt?

Lausn

Við getum raðað litunum og síað þann vinsælasta út með því að keyra

sort data/colors.txt | uniq -c | sort -nr | head -n 1
sem sýnir okkur algengasta litinn ásamt fjölda skipta.

Prófaðu: hæstu stigin

Sýndu þrjár hæstu línurnar í data/scores.csv eftir stigum. Sleppum hauslínunni fyrst.

Lausn

Við getum beitt tail og sort saman og keyrt

tail -n +2 data/scores.csv | sort -t, -k3 -nr | head -n 3
til að fá þá þrjá einstaklinga sem náðu hæstum árangri.

Annálar

Finndu þrjár algengustu vefslóðirnar í logs/access.log. Vefslóðin er sjöundi dálkurinn í skránni.

Lausn

Til þess að sía út sjöunda dálkinn og telja hann getum við keyrt skipunina

cut -d' ' -f7 logs/access.log | sort | uniq -c | sort -nr | head -n 3
sem birtir fljótt þær slóðir sem fengu flestar heimsóknir.

Vissir þú?

Pípur komu inn í Unix árið 1973. Hugmyndin var svo góð að hún breytti því hvernig fólk hannaði skipanalínuforrit: forrit þurftu ekki lengur að gera allt sjálf, heldur bara tala skýrt við næsta forrit í röðinni.

Verkefni

Hér má finna öll verkefnin úr efni þessa kafla.

Opna verkefni