Skip to content

Latest commit

 

History

History
396 lines (277 loc) · 16 KB

sed.md

File metadata and controls

396 lines (277 loc) · 16 KB

Sed

!Štítky: {program}{syntaxe}{zpracování textu} !OblíbenáZaklínadla: !ÚzkýRežim: zap

Úvod

„Sed“ je nástroj příkazové řádky pro editaci textového souboru (txt či txtz) po záznamech. Nejčastěji je užíván díky své schopnosti testovat záznamy vůči regulárním výrazům a nahrazovat jejich shody. Ve skutečnosti nenabízí o mnoho víc, takže tato kapitola bude spíše stručná. Jeho hlavními výhodami oproti konkurečním nástrojům jsou rychlost zpracování, přítomnost v prakticky každé instalaci linuxu, stoprocentní podpora UTF-8 a mimořádně úsporná syntaxe.

Sed pracuje tak, že v cyklu načítá záznamy ze vstupních souborů a na každý záznam spustí skript (zadaný typicky přímo na příkazové řádce, jen vzácně se ukládá do samostatného souboru).

GNU Sed je vyvíjen v rámci projektu GNU.

Definice

  • Prostor (space) je v Sedu oblast, do které se ukládají textové záznamy nebo jiné hodnoty. Existují pouze pevně definované prostory.
  • Pracovní prostor (pattern space) je prostor, do kterého se normálně na začátku každého cyklu přiřadí další načtený záznam. (Může však obsahovat i více záznamů.) Existují dva způsoby, jak na pracovní prostor nahlížet: většina příkazů ho vidí jako uspořádaný seznam záznamů, kde každý záznam je uveden včetně svého ukončovače; tzn. např. „ab\n“ a „cd\n“. Výjimkou je příkaz „s“, který vidí pracovní prostor jako řetězec, kde jsou tyto záznamy spojeny dohromady, ovšem ukončovač posledního záznamu je odsunut mimo. (Proto jsou-li např. v pracovním prostoru dva výše uvedené záznamy, příkaz „s/.*//“ skončí stejně vypsáním jedné prázdné řádky, protože závěrečný ukončovač zůstává mimo dosah příkazu „s“.)
  • Paměť (hold space) je pomocný prostor, do kterého lze záznamy z pracovního prostoru přenést či je tam připojit.
  • Příznak je booleovská proměnná používaná k podmíněným skokům (viz příkazy „s“, „t“ a „T“).
  • Vstupní data sed rozdělí na záznamy, což jsou ve výchozím stavu řádky (ukončené znakem „\n“), ale s parametrem „-z“ to budou bloky znaků ukončené nulovým bajtem („\0“).
  • Počítadlo záznamů je číselná proměnná – na počátku má hodnotu 0 a inkrementuje se pokaždé, když je ze vstupu načten záznam (tzn. pro první záznam už má hodnotu 1). Nikdy se nenuluje.

Cyklus sedu

Sed provádí zpracování vstupních souborů v těchto krocích:

1) Smaž pracovní prostor.

2) Pokud je na vstupu další záznam, načti ho a připoj na konec pracovního prostoru; jinak skonči.

3) Procházej skript, vyhodnocuj podmínky a vykonávavej odpovídající příkazy.

4) Vypiš pracovní prostor včetně odděleného ukončovače záznamu. (Tento krok se často z postupu odstraňuje voláním sedu s parametrem „-n“. Rovněž příkaz „d“ ho potlačí.)

5) Pokud nebyl v tomto cyklu skriptu proveden příkaz „q“, jdi zpět na krok 1.

Obecný tvar příkazu

Příkazy sedu mají obecný tvar:

*# *
{podmínka}[!]{příkaz}

Vykřičník neguje logickou hodnotu podmínky.

Je-li příkazů víc, odděluje je konec řádky („\n“), není-li odzvláštněn zpětným lomítkem. Pokud neposlední z příkazů neočekává jako parametr název souboru či obecný text, lze je oddělit také středníkem.

Místo jednotlivého příkazu může být také blok příkazů, které pak mohou mít svoje vlastní podmínky. V takovém případě sed nejprve otestuje podmínku bloku; není-li splněna, celý blok se přeskočí. Je-li splněna, sed do bloku vstoupí a jeho obsah vykoná, jako by podmíněn nebyl. Bloky lze zanořovat. Příklad, jak může vypadat blok:

*# *
/^a/!{
/test/d
/x/s/.*/&*/
}

Řetězec náhrady

V příkazu „s“ se uvádí „řetězec náhrady“, tedy řetězec, který definuje, za co se mají nahradit shody uvedeného regulárního výrazu. V tomto řetězci mají zvláštní význam znaky „\“, „&“ a znak ohraničující daný regulární výraz (obvykle „/“ či „!“); všechny lze odzvláštnit zpětným lomítkem.

Zvláštní významy znaků jsou následující: Za znak „&“ se dosadí původní text celé shody; za kombinace „\1“ až „\9“ se dosadí text podshody první až deváté skupiny v regulárním výrazu (skupiny se číslují podle pozice otevírací závorky). Za „\n“ se dosadí znak konce řádku, pro vložení nulového bajtu použije kombinaci „\x00“.

V řetězci náhrady také mohou být přepínače konverze velikosti písmen: „\L“ konvertuje následující znaky na malá písmena, „\U“ na velká písmena a „\E“ tuto konverzi vypne. „\l“ a „\u“ fungují analogicky, ale uplatní se jen na jeden následující znak.

!ÚzkýRežim: vyp

Zaklínadla

Podmínky (uvádějí se před příkaz)

Kteroukoliv podmínku lze negovat uvedením vykřičníku za podmínku.

# každý záznam
{prázdný řetězec}

# záznam odpovídající regulárnímu výrazu (alterantivy)
/{regulární výraz}/
\!{regulární výraz}!

# záznam odpovídající regulárnímu výrazu bez ohledu na velikost písmen (alterantivy)
/{regulární výraz}/I
\!{regulární výraz}!I

# rozsah mezi dvěma řádky danými čísly záznamů
{první-zahrnutý},{poslední-zahrnutý}

# rozsah mezi dvěma řádky odpovídajícími regulárním výrazům
// Poznámka: tento rozsah zahrnuje v sedu vždy alespoň dva záznamy. Pokud už první záznam rozsahu odpovídá regulárnímu výrazu pro poslední záznam, sed to ignoruje!
/{reg. výraz pro první záznam}/[I],/{reg. výraz pro poslední záznam}/[I]

# konče/počínaje určitým záznamem
1,{poslední-zahrnutý}
{první-zahrnutý},$

# první/poslední záznam
1
$

# dva první/poslední záznamy
1,2
?

# všechny záznamy až po první záznam odpovídající regulárnímu výrazu včetně
0,/{regulární výraz}/[I]

# záznam odpovídající regulárnímu výrazu a N následujících
/{regulární výraz}/[I],+{N}

# rozsah od záznamu odpovídajícího regulárnímu výrazu po následující záznam, jehož číslo je celočíselným násobkem N
/{regulární výraz}/[I],~{N}

# liché/sudé záznamy
1~2
2~2

# každý třetí záznam, počínaje sedmnáctým
17~3

Zaklínadla: Příkazy

Operace s pracovním prostorem

# provést náhradu v pracovním prostoru (alternativy)
// Volby mohou být: „g“ (nahradí všechny shody), kladné celé číslo (nahradí pouze tolikátou shodu), „i“ (nebude rozlišovat velká a malá písmena). Volby lze skombinovat, např. „2i“. V případě, že příkaz „s“ najde požadovanou shodu, nastaví příznak na hodnotu 1; v opačném případě příznak nemění(!).
s/{regulární výraz}/{řetězec náhrady}/[{volby}]
s!{regulární výraz}!{řetězec náhrady}![{volby}]

# načíst další záznam do pracovního prostoru (přepsat stávající/přidat za stávající)
n
N

# nahradit znaky
// Řetězce musejí mít přesně stejnou délku. Příkaz „y“ projde pracovní prostor znak po znaku a každý znak, který se nachází v řetězci 1 nahradí znakem na stejné pozici v řetězci 2. Vždy provede pouze jednu náhradu, takže tento příkaz je možno využít i k prohození dvou znaků.
y/{řetězec 1}/{řetězec 2}/

# nahradit ukončovače záznamu (\n nebo \0) kromě posedního
s/\n/{řetězec náhrady}/g
s/[\x00]/{řetězec náhrady}/g

# přiřadit do pracovního prostoru jeden prázdný záznam
z

# odstranit první záznam
?

Skoky

# na konec skriptu (nevypisovat pracovní prostor/normálně/nezačínat další cyklus)
d
b
q

# podmíněný skok (skočit, pokud je příznak 1/pokud je 0)
// Příkazy t a T příznak nulují vždy, i když ke skoku nedojde!
t[{návěští}]
T[{návěští}]

# návěští pro skoky
// Návěští je příkaz, ale nepřijímá „podmínku“.
:{návěští}

# skok na návěští
b{návěští}

# okamžitě ukončit zpracování
Q

# je-li v pracovním prostoru víc záznamů, smazat první z nich a skočit na začátek skriptu; jinak se chová jako příkaz „d“
D

Výpis na výstup

# vypsat pracovní prostor na standardní výstup (všechny záznamy/jen první záznam)
p
P

# vypsat pracovní prostor do souboru (všechny záznamy/jen první záznam)
// Poznámka: pokud soubor existuje, před prvním zápisem bude vyprázdněn!
w{jméno/souboru}
W{jméno/souboru}

# vypsat číslo záznamu (jako záznam)
=

# vypsat konkrétní záznam
// Pozor, jednotlivé řádky se vždy oddělí znakem „\n“, ale ukončí se aktuálním ukončovačem záznamu („\n“ nebo „\0“).
i\
[{řádek záznamu}\]
{poslední řádek záznamu}

Operace s pamětí

# přiřadit obsah pracovního prostoru do paměti (hold)
h

# přiřadit obsah paměti do pracovního prostoru (get)
g

# vyměnit obsah pracovního prostoru a paměti
x

# připojit obsah pracovního prostoru na konec paměti
H

# připojit paměť na konec pracovního prostoru
G

Komentář

# komentář
# {komentář do konce řádky}

Parametry příkazů

sed

*# *
sed {parametry} [-e] '{skript}' [{vstupní-soubor}]...
sed {parametry} -f {soubor-se-skriptem} [{vstupní-soubor}]...
[sudo] sed -i {parametry} [-e] '{skript}' {soubor}
[sudo] sed -i {parametry} -f {soubor-se-skriptem} {soubor}

!parametry:

  • ☐ -E :: Použije rozšířené regulární výrazy místo základních. (Tento parametr doporučuji důsledně používat, kdykoliv ve skriptu hodláte použít regulární výraz!)
  • ☐ -n :: Odstranit z cyklu automatické vypisování pracovního prostoru.
  • ☐ -z :: Záznamy jsou ukončeny „\0“ místo „\n“.
  • ☐ -i :: Místo vypsání na výstup přepíše výstupem vstupní soubor.
  • ☐ --debug :: Na výstup vypíše čitelné ladicí informace o činnosti skriptu.
  • ☐ -u :: Ze vstupu načítá jen minimální množství dat.

Instalace na Ubuntu

GNU sed je základní součástí Ubuntu přítomnou i v minimální instalaci.

Ukázka

# skript.sed
/no/d
# pokud obsahuje „1“, třetí velké či malé „x“ uzavřít do závorek,
# ne však na řádcích 7 až 12
7,12!{/1/s/x/(&)/3i}
# liché řádky velkými písmeny, před sudé pomlčku
2~2s/.*/␣-␣&/
1~2s/.*/\U&/
p
# chybové hlášení, pokud stejná řádka obsahuje jablko i hrušku
/jablko/I{/hruška/I{i\
Chyba: nemíchejte jablka s hruškami!
}}

# volání
sed -nE -f skript.sed
!: a pište nějaké řádky textu. Sed ukončíte zkratkou Ctrl+D.

!ÚzkýRežim: zap

Tipy a zkušenosti

  • Programovat v sedu cokoliv složitějšího je namáhavé, nepraktické a náchylné na chyby. Pokud vám nestačí jen několik základních příkazů, je mnohem rozumnější použití složitějších nástrojů jako „GNU awk“ či „Perl“.
  • Skripty v sedu dovedou být extrémně nesrozumitelné. Dovedli byste na příklad říci, co udělá „sed -E '\!testy!I!s!s!x\!!i'“?
  • Malé textové soubory je často výhodné zpracovat najednou zadáním parametru „-z“. Když vstupní soubor neobsahuje nulový bajt, sed v takovém případě načte celý soubor jako jeden záznam.

Další zdroje informací

Zákulisí kapitoly

V této verzi kapitoly chybí:

!KompaktníSeznam:

  • nic

Tato kapitola záměrně nepokrývá:

!KompaktníSeznam:

  • nic

!ÚzkýRežim: vyp