A sed fontosabb parancsai

A fentiek után, ha csak röviden is, tekintsük át a sed leggyakrabban használt parancsait. Mivel a legtöbb parancs akár nulla, akár egy vagy két címmel is megadható, a címmegadást a következőek szerint jelöljük: ha a parancs csak egy címet fogad el, a /sorcím/ jelölést alkalmazzuk, ha kettőt, akkor a /címtartomány/ jelölést.

Behelyettesítés

[címtartomány] s / minta új_minta / [jelzők]

A címtartomány által meghatározott tartományban lévő sorokban behelyettesíti minta helyére új_mintát. Mind címtartomány, mind minta lehet reguláris kifejezés, az összes ott megismert metakarakter használható megadásukkor. Ha címtartomány reguláris kifejezés, és azonos minta-val, azaz minta megadása nem kötelező (pl. a /kutya/s//macska/g parancs minden, a kutya szót tartalmazó soron fog végrehajtódni, s ott minden kutyát lecserél macskára).

Módosító flagek

Behelyettesítéskor az alábbi jelentésmódosító flagek használhatóak:

n 1 és 512 közti szám, mely azt jelzi, hogy a behelyettesítést minta n-edik előfordulásán kell csak végrehajtani

g a mintatérben minta összes előfordulását lecseréli, nem csak a legelsőt, amit talál

p kilistázza a mintatér tartalmát

w file a mintatér tartalmát a file állományba írja

Metakarakterek a keresendő minta megadásakor

A keresendő mintát a reguláris kifejezéseknél megismert módon adhatjuk meg, az ott megismert metakarakterek használhatóak.

Metakarakterek a behelyettesítés megadásakor

Az alábbi metakarakterek a behelyettesítés jobb oldalán használhatóak.

& minta értékének felel meg. Például s/Egyesült Államok/Amerikai &/ hatására sed a teljes névre egészíti ki slendrián megfogalmazásunkat.

\n (n egyjegyű egész szám); a mintában, tehát a behelyettesítés baloldalán a reguláris kifejezésben szereplő n-edik, \( .. \) karakterek közé zárt reguláris alkifejezésre hivatkozik. Például az s/\([A-Z][a-z][a-z]*\) \([A-Z]\.\) \([A-Z][a-z][a-z]*\)/\3 \1 \2/ parancs hatására a köznapi formában írt angolszász neveket alakítja át "hivatali használatra", például John C. Smith helyett Smith, John C. formára. (Lefordítva a fenti, valóban meglehetően ronda kifejezés valami olyasmit csinál, hogy "első reguláris alkifejezés legyen egy nagybetűvel kezdődő, egy vagy több kisbetűt tartalmazó karaktersorozat, ezt szóköz követi, a második alkifejezés egy nagybetű, melyet egy pont karakter követ; szóköz, majd a harmadik alkifejezés ismét csak nagybetű, egy vagy több kisbetűvel követve; ha a mintatérben talált a sed erre illeszkedő mintát, a harmadik, az első és a második alkifejezésre illeszkedő részét írja a kimenetre".)

\ több funkciót is ellát, egyrészt a másik két metakarakter speciális jelentését nyomja el, másrészt többsoros behelyettesítés megadásánál használatos. Többsoros behelyettesítésre lehet példa az alábbi, ahol ha a

sed 's/\.ti \([0-9][0-9]*\) \(.*\)/\1. fejezet\

\2/'

parancs a

 

.ti 3 Az cserebogarak halhatatlansagarul

veretes szövegformázó makróutasítást a

 

3. fejezet
Az cserebogarak halhatatlansagarul

kétsoros formára hozza.

Törlés

[címtartomány]d

A d parancs a kijelölt sort vagy sorokat törli (részleges törlésre a substitute parancsot használhatjuk). Egy dolgot kell ezzel kapcsolatban megemlítenünk: ha egy sort kitörlünk a mintatérből, a feldolgozás értelemszerűen megszakad, új sor kerül be a mintatérbe, s a sed scriptben szereplő parancsok annak feldolgozását kezdik meg.

Hozzáfűzés, beszúrás, változtatás

[sorcím]a\

szöveg

[sorcím]i\

szöveg

[címtartomány]c\

szöveg

Az a (append) parancs a mintatérben lévő sor végére, az i (insert) parancs a mintatérben lévő sor elejére, a c (change) parancs pedig a mintasor helyett illeszti be szöveget. Vigyázzunk arra, hogy mindhárom parancs többsoros, a parancs betűje után mindenképpen kell a backslash karakterrel védett soremelés, s kell a szöveg sorainak végén is, ha a beillesztendő szöveg többsoros. Szokatlan lehet az is, hogy a beillesztett szöveg kiíródik ugyan a kimenetre, de nem képezi részét a mintatérnek, s így a soronkövetkező script parancsok nem veszik figyelembe a sor feldolgozásánál. Mivel a c parancs törölte az eredeti mintateret, a szóban forgó sor feldolgozása éppúgy megszakad, mintha a d vagy q parancsot adtuk volna ki.

Transzformáció

[címtartomány] y / str1 str2 /

Az y (olvasd: transform... :-) parancs a mintatérbe kerülő sorokon karakterkonverziót hajt végre, mégpedig úgy, hogy mindazon karaktereket, melyek str1-ben szerepelnek, a mintatérben str2 ugyanazon pozíción lévő karakterével helyettesíti. (Gyakorlatilag a tr nevű Unix parancs mintájára.) Az alábbi sed parancs például minden számjegyet az N betűvel helyettesít a kimeneten:

 

sed 'y/0123456789/NNNNNNNNNN/'

 

Nyomtatás

[címtartomány]p

A p (print) parancs a mintatér tartalmát írja ki a mindenkori kimenetre. Miután a sed alapértelmezés szerint a mintatér minden sorát kiírja, a p parancsot a hibakeresés miatti kiíráson kívül a leginkább akkor használjuk, ha a sed parancsot a -n opcióval hívtuk meg, azaz alapértelmezésben letiltottuk a sorkiírást. (Ha például bizonyos részeket keresünk egy fájlban, s nem módosítani akarjuk, e megoldás a célravezetőbb.)

 

sed -n '/Linux/p'

A fenti parancs hatására a Linux szót tartalmazó sorok íródnak ki, a sed a többit eldobja.

Új sor beolvasása

[címtartomány]n

Az n (next) parancs hatására a mintatér pillanatnyi tartalmát sed kiírja a kimenetre, törli azt a mintatérből, majd beolvassa a soron következő sort, s azon folytatja a script parancsainak végrehajtását. Az alábbi parancs a '.' karakterrel kezdődő sorok után beolvassa a következő sort (vigyázat, ekkor az eredetit már a kimenetre tette!), s ha az újonnan beolvasott sor üres volt, törli azt:

 

sed '/^\./ { n

/^$/d }'

Fájlok írása-olvasása

[sorcím]r file

[címtartomány]w file

Az r (read) paranccsal a megadott cím után olvassa be a sed a mintatérbe file tartalmát; w (write) hatására a megadott címtartományon belüli rész kerül ki file-ba. Szintaktikai finomság: mindkét parancs pontosan egy szóközt követel meg a parancs és a fájlnév között; ha többet adunk meg, azt a fájlnév részének fogja tekinteni. Ha nem létező fájlt akarunk olvasni, a sed nem panaszkodik; hasonlóképp, nem létező fájl írásakor létrehozza azt, már létező tartalmát pedig felülírja. (A scripten belüli többszöri írások hozzáfűznek a fájlhoz.)

Az a, i és c parancsokhoz hasonlóan az r parancsra is igaz, hogy azonnal sed kimenetére kerül, s a script további feldolgozásában, mintaillesztésében nem vesz részt, a mintatérben maradó eredeti sor viszont igen. Egy példa ennek illusztrálására:

Tegyük fel, hogy van egy template nevű mintafájlunk, az alábbi szöveggel:

 

Kedves Ismeretlen, On cegunktol az alabbi ingyenes alomutazasok valamelyiket nyerte:

<cimlista>

Ezek igenybevetelehez mindossze az alabbiakat kell tennie...

A behelyettesítendő adatok pedig a helyszin.txt nevű állományban találhatóak:

 

Kanari szigetek repulogeppel

Korfu szigete autobusszal

Margit-sziget vízibusszal

Ha ezek után a sed-et a

 

sed '^/<cimlista>/ { r helyszin.txt ; d }' template

paranccsal hívjuk meg, akkor helyszin.txt szövege beszúródik a mintatér végére; a következő d parancs viszont a mintatér eredeti tartalmát törli, s így amikor a sed végzett az adott sorral, <cimlista> helyett a felkínált helyek listája jelenik meg a kimeneten:

 

Kedves Ismeretlen, On cegunktol az alabbi ingyenes alomutazasok valamelyiket nyerte:

Kanari szigetek repulogeppel

Korfu szigete autobusszal

Margit-sziget vízibusszal

Ezek igenybevetelehez mindossze az alabbiakat kell tennie...

 

Több sor kezelése

N

D

P

Alábbi parancsaink az eddig ráolvasásszerűen ismételgetett dogmát kezdik ki, miszerint a sed sororientált editor, s egyszerre mindig csak egy soron végez műveleteket. Az N, D és P parancsok funkcionalitásukban egysoros megfelelőikkel azonosak, de mindegyik több soron dolgozik.

N hatására sed még egy sort olvas a bemenetről, s a mintatér végére fűzi, annak régi tartalmát is megőrizve. A mintatérben lévő sorokat az újsor '\n' karakter választja el, s erre a mintakereséseknél hivatkozhatunk is. (Lásd a következő példát.)

D hatására a mintatérből egy sor, azaz a mintatér elejétől az első újsor karakterig terjedő rész törlődik. Ellentétben a d paranccsal, hatására nem olvas be új sort a mintatérbe, a feldolgozás viszont itt is újra a script elejétől folytatódik. Klasszikus példa a D parancs felhasználására, amikor sok üres sort tartalmazó bemenetről szeretnénk kiszűrni a felesleges sorokat:

 

/^$/ {

N

/^\n$/D

}

(A megoldás azon alapul, hogy üres sor beolvasása után a sed még egy sort beolvas, ha az is üres, az elsőt kitörli, s a script végrehajtása elölről indul; azaz mindez a beolvasás és törlés addig folytatódik, amíg vannak többszörös üres sorok, a script egyesével araszol végig a beolvasott sorokon. Ugyanez a d parancs felhasználásával páratlan számú üres sorokra nem működik, hiszen a d parancs a teljes mintateret, azaz mindkét sort törölte volna, a harmadik üres sor beolvasása után viszont nem üres sor jönne, s a script ekkor már nem törölné a harmadik üres sort.

P hatására sed a mintatérből az első újsor karakterig terjedő részt írja a kimenetre. Önmagában nem gyakran használják, tipikus alkalmazása az előző példában szereplő, többsoros mintákat vizsgáló alkalmazásokban lehet. Ha ugyanis több egymás utáni sorban kell mintát keresni és behelyettesítést végezni, a legcélszerűbb megoldás egy olyan hurok felépítése, ahol megfelelő számú N paranccsal beolvassuk a mintatérbe a vizsgálandó sorokat, a megfelelő behelyettesítések után P paranccsal kiírjuk a mintatér módosított első sorát, majd ugyanazt töröljük a D paranccsal a mintatérből. A script megint elölről kezdi a feldolgozást, egy sorral odébb csúsztatva a "vizsgálati ablakot" a bemeneten. Alanti programocskánk (hasznosságáról valószínűleg nem kell győzködni a tisztelt olvasót :-) a netalán helytelenül írt Kisfejű Zordonbordon neveket cseréli ki az autentikus Kisfejű Nagyfejű Zordonbordonra, abban az esetben is, ha az a sorhatáron átnyúlva zordonbordonkodik:

Ha a tesztfájlunk az alábbi:

 

Mikor tegnap erre jott Kisfeju

Zordonbordon,

morcosan nezett a Kisfeju Zordonbordon,

hogy nevet mindig rosszul mondom

a script pedig ez:

 

/Kisfeju/ {

N

s/Kisfeju\(.Zordonbordon\)/Kisfeju Nagyfeju\1/g

P

D

}

az eredmény ez lesz:

 

Mikor tegnap erre jott Kisfeju Nagyfeju

Zordonbordon,

morcosan nezett a Kisfeju Nagyfeju Zordonbordon,

hogy nevet mindig rosszul mondom

A script a Kisfeju szót tartalmazó sorok esetén beolvassa a következő sort is, s a kétsoros mintatéren globális behelyettesítést hajt végre, azaz a keresett minta összes előfordulását javítja: A Zordonbordon szót és az azt megelőző (szóköz vagy újsor) karaktert reguláris alkifejezésként megjelöltük, s a behelyettesítéskor ugyanezt tesszük vissza. Miután fenti módon az összes nevet kicseréltük, a mintatér első sorát (ami garantáltan javított), kiírjuk, majd töröljük a mintatérből, újabb sort olvasunk be, s újra kezdődik a script végrehajtása.

Az ideiglenes tárolótér és parancsai

A mintatéren kívül, ami mindig az aktuális sort tartalmazza, a sed egy másik területet is fenntart, ez a hold space (jobb híján nevezzük tárolótérnek). Ha egyes műveletek során arra volna szükségünk, hogy a mintatért elmentsük valahova, míg eredeti tartalmán műveleteket hajtunk végre, a tárolótérben tudunk egy ideiglenes kópiát képezni. A tárolóteret öt, nem címezhető parancs kezeli: h, H (hold), g, G (get) és x (exchange). A hold parancsok hatására a tárolótér tartalma a mintatérbe kerül, a get parancsok hatására pedig a tárolótér tartalma kerül vissza a mintatérbe. Az exchange parancs hatására a tárolótér és a mintatér tartalma megcserélődik. A kis- és nagybetűs parancsok között az a különbség, hogy h és g bemásoláskor felülírja a tároló-, illetve a mintatér tartalmát, H és G pedig újsor karakterrel elválasztva hozzáfűzi annak tartalmához (az újsor karaktert akkor is beteszi, ha a minta- vagy tárolótér éppen üres volt).

Elágazások, feltételes parancsvégrehajtás

Számos olyan sed parancsot láttunk már, melyek implicit módon megváltoztatják a scriptben a feldolgozás folyamatát; az alábbiakban olyan parancsokkal zárjuk ismerkedésünket a sed-del, melyek kimondottan a parancsvégrehajtás folyamatát szabályozzák.

Címkék

A címkék használata teszi lehetővé, hogy általunk kijelölt tetszőleges helyre ugorhassunk egy sed scriptben. A címke egy maximum hét karakterből álló sorozat, melynek kettősponttal megelőzve, egymagában kell egy sorban szerepelnie, hogy a sed felismerje. (Rendkívül gyakori hiba, hogy a címke és a sor vége között néhány szóköz karaktert felejt az ember; ne tegyük, mert hét karakterig bezárólag ezeket is a címke részének tekinti a sed!) Ha egy parancsban címkére hivatkozunk, a script végrehajtása a címkét követő soron folytatódik. Például az alanti scriptrészlet hatására a loop3 címkére ugráskor a sed a mintatér tartalmát a tárolótér tartalmához fűzi, majd törli a mintatér első sorát:

:loop3

{

H

D

}

Elágazás

[címtartomány]b[címke]

A b (branch) parancs hatására a script vezérlése a label címkét követő sorra adódik át; ha nem adtunk meg címkét, a vezérlés a script végére kerül, magyarul a mintatér tartalma kiíródik és új sort olvas be a sed. (A b parancs és a címke között megengedett a szóközök használata.)

Például a

 

/^\.start/,/^\.stop/!b

s/\(.*\)/> \1/

script hatására a .start- .stop parancsokkal kijelölt rész kivételével (figyeljünk a negáló '!' karakterre!) nem csinál semmit, mert a vezérlést a script végére adja át. A .start és .stop parancsok közti részen pedig minden sort elé elhelyez egy '> ' szekvenciát.

A branch parancs segítségével hurkokat is tudunk csinálni:

 

:eleje

parancs1

/minta/b eleje

parancs2

A fenti programstruktúra alkalmazásával parancs1 mindaddig ciklikusan végrehajtódik, amíg a bemeneten van minta-ra illeszkedő sor; ha nincs, a script végrehajtása parancs2-vel folytatódik. Hasonló módon alakíthatóak ki egyéb ciklikus vezérlési szerkezetek is.

 
Feltételes elágazás

[címtartomány]t[címke]

A t (test) parancs hatására a vezérlés akkor kerül a megadott címke utáni sorra, ha előzőleg a kurrens sorban sikeres behelyettesítés történt. Akárcsak a b parancsnál, címke elhagyása esetén a vezérlés a script végére adódik át. Az alábbi script a .pa makróutasítás helyett egy soremelés (CTRL-L) karaktert szúr be, a .pp makróutasítás helyett pedig egy újsor karaktert. Mindkét esetben, ha sikeres volt a behelyettesítés, a vezérlés a tovabb címkétől folytatódik; gyakorlatilag tehát egy C vagy shell nyelvi case konstrukciót szimulálunk:

 

/^\.pa.*/s//^L/

t tovabb

/^\.pp.*/s//\n/

t tovabb

... egyeb parancsok

:tovabb

A fentiekben csak igen vázlatos áttekintését nyújtottuk a sed-nek, de azt talán sikerült bizonyítanunk, hogy rendkívül sokoldalúan használható eszköz lehet a felhasználó kezében. Csak bátorítani tudunk mindenkit használatára, mert a kezdeti erőfeszítések sokszorosan kifizetődnek majd az első komolyabb szövegátalakítás alkalmával.

 

Tartalomjegyzék