Hlavní navigace

Drobnosti ze shellového zápisníku (4)

Stanislav Brabec

Dnes se podíváme na méně známé proměnné, na možnosti výzvy shellu a na praktické regulární výrazy, které používám pro psaní článků na Roota. Více procesů nám předvede malý skript, který umožňuje zadávat jména souborů během skenování. Skončíme ukázkou, jak pomocí shellu uklidit před archivací soubory v hotové zakázce.

Zajímavé proměnné, které možná neznáte

Proměnné pro národní prostředí

Většina z vás jistě zná proměnnou LANG, která slouží pro nastavení národního prostředí. To však není zdaleka vše, co nám může lokalizace nabídnout.

Kromě LANG zde existuje ještě sada proměnných
LC_vlastnost pro jednotlivé vlastnosti (jazyk, znaková sada,
kategorie znaků aj.) a LC_ALL, která „přebije“ proměnnou
LANG, a proto je vhodná do skriptů, kde je nutné použít určité národní
prostředí.

Vedle těchto proměnných však existuje ještě proměnná LANGUAGE. Ta nemění žádnou kategorii znaků, ale vybírá jazyky, kterými bude počítač komunikovat. Například na svém počítači mám tyto proměnné nastaveny následovně:

LANG=cs_CZ.ISO-8859–2
LANGUAGE=cs_CZ.ISO-8859–2:sk_SK.ISO-8859–2
export LANG LANGUAGE

Toto nastavení instruuje všechny lokalizované programy, že mají komunikovat česky. Pokud však nenajdou překlad pro český termín, hledají ještě slovenský. Můj systém tedy není česko-anglický, ale česko-slovensko-anglický.

CDPATH

Další užitečnou proměnnou je CDPATH. Udává seznam adresářů, které bude příkaz cd prohledávat, má-li najít cíl. Nastavím tedy:

CDPATH=„.:~:/us­r/src“

Pak mne třeba cd linux automaticky přepne do adresáře /usr/src/linux, aniž bych musel cestu přímo vypisovat.

Hrátky s výzvou (prompt)

Výzvu (prompt) lze v moderních shellech, jakým je např. Bash, pozměnit dle
své potřeby. Řídí ji čtyři proměnné PS1 až PS4. Základní
výzvou je PS1. Její běžná standardní hodnota je \h:\w\$. Ta
dává základní informaci – počítač, adresář a zda jde
o superuživatel­ský účet.

Pokud pracujeme s terminálovými okny pod X11, můžeme výzvu zobrazit v titulku okna. Text do titulku okna lze vypsat pomocí:

echo -en ‚\e]0;Text v titulku okna\007‘

Příslušná výzva musí dát shellu na vědomí, že znaky v titulku nelze zahrnout do počtu znaků vypsaných na řádce:

PS1='\[\e]0;\­u@\h:\w\a\]\$ '

Komplikovanější úkoly můžeme vyřešit pomocí příkazu nastaveného do PROMPT_COMMAND. Pokud pracujete na vytáčené lince, může vás inspirovat následující příklad, který přidá do výzvy znak +, pokud jste připojeni, a znak -, pokud nejste připojeni k Internetu (test bude zřejmě nutné modifikovat pro různé distribuce a způsoby připojení).

PROMPT_COMMAND=‚A= if test -f /etc/ppp/resolv.conf ; then echo + ; else echo - ; fi
PS1=‚\h:\w $A\$ ‘

Chcete-li, aby se každý příkaz ihned po svém dokončení zapsal do historie, můžete PROMPT_COMMAND nastavit na history -a. Následující nastavení pak umožňuje okamžité sdílení historie mezi několika instancemi shellu, což ocení hlavně ti, kteří mají běžně otevřeno deset příkazových oken:

PROMPT_COMMAN­D=‚history -a ; history -n‘

Třetí příklad se hodí těm, kteří spouštějí časově náročné aplikace na mnoha počítačích. Po dokončení každého příkazu oznámí shell tuto skutečnost mailem:

PROMPT_COMMAN­D=‚rc=$? ; (history | tail -n 1 ; echo skončil s návratovou hodnotou $rc) | mutt -s „příkaz na hostname skončil“ adresa

Touto tématikou se zabývá celé jedno z oficiálních HOWTO – Bash-Prompt-HOWTO. Tam najdete i další příklady.

Praktické regulární výrazy

Na regulární výrazy jsme v zápisníku již narazili. Dnes si ukážeme další, které pravidelně používám pro články na Roota. Protože pracuji s Emacsem, uvádím jak verzi pro sed (tam se musíme vyhnout problémům s konci řádků – viz minulý díl), tak pro Emacs (globální záměnu je možné provést pouze na text bez HTML značek používajících uvozovky).

# uvozovkovač (převádí jednoduché uvozovky na uvozovky dole a nahoře)
s/„\([^“]*)„/­\„\1\“/g
# uvozovkovač pro Emacs
zdroj regexp-záměny: "\([^“]*)"
cíl regexp-záměny: „\1“

Český pravopis zakazuje výskyt jednopísmenných předložek na konci řádku. Podle typografických pravidel to platí ještě pro spojky: A, I,

i. Příslušné programy se nazývají „vlnkovače“ –
prvně byly použity v TEXu, kde znak ~ zakazuje zlom
řádku. V HTML si pomůžeme znakem  :

# připojení jednopísmenných předložek
:1;s/\([ ¤;>({][svzkuo­iSVZKAUOI])[ ¤][ ¤]*/\1\ /g;t1
# připojení jednopísmenných předložek pro Emacs (nutno spustit dvakrát)
zdroj regexp-záměny (víceřádkový): \([
;>({][sv­zkuoiSVZKAUOI])[
]+
cíl regexp-záměny: \1 

Je třeba pamatovat na to, že regulární výrazy pro Emacs se mírně liší od těch pro sed – rozdíly spočívají v tom, jak se odliší znak & od své expandované podoby a dále v možnosti použít jako kvantifikátor znak + ve významu „nejméně jeden výskyt“.

Více procesů

Často skenuji najednou větší množství CD bookletů, u kterých je důležité zadat správné jméno (katalogové číslo). V běžném GUI programu jsem nejdříve čekal, než se dokončí skenování, a pak pro změnu čekal počítač, než napíšu jméno.

UNIX je naštěstí víceúlohový systém. Proto i shell zvládá více procesů. Stačí použít znak & za příkazem a příkaz wait. V následující ukázce rodičovský proces čeká na jméno souboru, zatímco potomek již skenuje obrázek.

Skript scanbooklet:

#! /bin/sh

# skenovací příkaz v procesu potomka
scanimage umax:/dev/scanner --resolution=600 --mode=Color \
 -l 0mm -t 0mm -x 120mm -y 120mm >tmp.tif &

# zadání jména
echo -n "Jméno obrázku (bez přípony): "
read name

# počkat, pokud skenování ještě neskončilo
wait

# přejmenování
mv -i -v tmp.tif $name.tif

Ti, kteří četli pozorně seriál o grafice, jistě vědí, že tím cesta obrázku nekončí, ale následuje zmenšení (a tím i rozbití rastru), gama korekce, ruční oříznutí, a poté převod do formátu JPEG. Skutečně používaný skript je navíc trochu složitější, protože se do mého skeneru vejdou dva booklety.

Úklid hotové zakázky

Před archivací smažu všechny generované soubory. Protože většina zakázek není programátorského charakteru, žádné make clean není k dispozici. Po dokončení práce v TEX se adresáře hemží soubory s příponami tif, jpg, eps, tex,

log, aux. Část z nich nemá pro rekonstrukci zakázky význam,
protože je lze snadno vygenerovat. Ovšem např. všechny soubory eps
nelze smazat – některé jsou generované z tif nebo
jpg souborů, jiné jsou původní vektorovou grafikou. Pro usnadnění
práce jsem napsal jednoduchý skript, který si každý může přizpůsobit podle
svých potřeb.

Skript uklid:

#! /bin/bash
shopt -s nullglob

smaz() {
  suffix=$1
  shift
  for i in *.$suffix ; do
    for j in $@ ; do
      rm -v -f "${i%.$suffix}.$j"
    done
  done
}

smaz jpg eps
smaz tif eps
smaz png eps
smaz dvi ps
smaz tex dvi aux toc ind idx log

# smazat náhledy a stav Emacsu
then rm -r -v .xvpics .thumbnails .emacs.desktop

A to je ze shellového zápisníku prozatím všechno.

Našli jste v článku chybu?