Portál AbcLinuxu, 8. května 2024 01:23
V předposlední části seriálu si ukážeme, jak pracovat s dokumenty here, metaznaky shellu, regulárními výrazy, filtry a proudovými editory.
Umožňují předat vstup příkazu ze samotného skriptu. Ukážeme si to na skriptu here.sh
.
#!/bin/bash
|
Ještě si skript spustíme.
# ./here.sh
$USER=root
|
Lze je použít k neúplnému zadání jména souboru.
POZOR neztotožňujte metaznaky shellu s regulárními výrazy, jsou to dvě různé věci. Metaznaky expanduje přímo shell. A proto když chceme nějakému programu předat regulární výraz, musíme ho uzavřít například do apostrofů.
*
- libovolný řetězec (může být i nulové délky)?
- libovolný jeden znak~
- domovský adresář ($HOME)~UJ
- domovský adresář uživatele UJ~+
- aktuální pracovní adresář ($PWD)~-
- předchozí pracovní adresář ($OLDPWD)[abc...]
- jakýkoliv znak uvedený v [], lze použít - k
zápisu intervalu znaků např a-z, 0-9[!abc...]
- opak předchozího (tj. jakýkoliv znak mimo
uvedených znaků v [])První příkaz smaže zálohy souborů (soubory končící na ~
).
Znak ~
nebude v tomto případě expandován.
$ rm *~
|
Jsou (mými slovy, přesná definice je "trochu" složitější )
vzory, s jejichž pomocí lze definovat společné rysy několika různých
řádků a tím pádem je reprezentovat jako jeden regulární výraz.
Níže uvedené speciální znaky jsou použitelné např. v grep
,
egrep
, sed
, ed
, ex
,
awk
.
.
- jakýkoliv znak (mimo znaku nového řádku)*
- libovolný počet (i nulový) opakování předchozího
znaku (lze použít i regulární výraz)^
- následující výraz musí odpovídat začátku řádku$
- předchozí výraz musí odpovídat konci řádku\
- vypíná speciální význam následujícího znaku[]
- jakýkoliv znak uvedený v hranatých závorkách,
speciální znaky zde mají normální význam, mimo
-
tu lze použít pro zápis intervalů
(a-z atd.) a znak ^
uvedený jako
první způsobí negaci (tj. jakýkoliv znak
neuvedený v ...)Použijeme programy cat
, grep
a všechno
si poctivě vyzkoušíme.
$ cat << END > ./retezce.txt > abclinuxu > alfa > aaa > abcabcabc > znak $ > a1a > aAa > END $ cat ./retezce.txt | grep '.*' abclinuxu alfa aaa abcabcabc znak $ a1a aAa $ cat ./retezce.txt | grep '.* \$' znak $ $ cat ./retezce.txt | grep '^a[a-z]*a$' alfa aaa $ cat ./retezce.txt | grep '^a[a-z0-9]*a$' alfa aaa a1a |
Jsou programy, které ze vstupu podle zadaného vzoru odfiltrují
jen námi požadovaná data a pošlou je na výstup. Jsou jimi např.
grep
, egrep
(grep -E
) a
fgrep
(grep -F
), jsou to vlastně stejné
programy. Pro nás je důležité, že grep
používá pro
zápis regulárních výrazů starší notaci a egrep
naopak
novější notaci. Níže uvedené speciální znaky patří do novější notace
a chceme-li je použít ve filtru grep
, musíme před ně
zapsat znak \
.
+
- jeden a více výskytů předchozího výrazu.?
- jeden nebo žádný výskyt předchozího výrazu.|
- předcházející nebo následující výraz.()
- text odpovídající výrazu mezi závorkami se
uloží do paměti a lze ho použít pomocí
\1
až \9
, čísluje se
od vnějších závorek směrem dovnitř
(např. ((abc)linuxu) \1
= "abclinuxu") a \2
= "abc". Nebo
lze použít závorky k definování priority
vyhodnocení.{n,m}
- interval opakování předchozího výrazu,
{n} - opakuje se n-krát, {n,} n-krát a více,
{n,m} n-krát až m-krátPro lepší pochopení uvedu opět několik příkladů.
$ cat ./retezce.txt | grep '^a\+$' aaa $ cat ./retezce.txt | egrep '^a+$' aaa $ cat ./retezce.txt | egrep '^abcl?' abclinuxu abcabcabc $ cat ./retezce.txt | egrep '^c|z' znak $ $ cat ./retezce.txt | egrep '(abc)+' abclinuxu abcabcabc $ cat ./retezce.txt | egrep '^(.*)\1\1$' aaa abcabcabc $ cat ./retezce.txt | egrep '^a{3}$' aaa $ cat ./retezce.txt | egrep '^a{2,}$' aaa $ cat ./retezce.txt | egrep '^a{1,3}$' aaa |
Z názvu je zřejmé, že slouží k proudové editaci dat. O načítání vstupu
se starají sami. Mají k dispozici sadu příkazů, pomocí které data upravují
(obvykle pracují s jedním řádkem), např. sed
a nebo na
složitější věci awk
.
Syntaxe příkazu:
Začátek,Konec!InstrukceArgumenty
Začátek
- číslo řádku ($ značí poslední řádek) nebo
/regulární výraz/Konec
- číslo řádku nebo /regulární výraz/!
- neguje předchozí bodyInstrukce
- mají jedno písmenoArgumenty
- k některým instrukcímNení-li uveden Začátek
a Konec
, aplikuje
se instrukce na každý vstupní řádek. Je-li uveden pouze
Začátek
, aplikuje se instrukce pouze na odpovídající řádek
(či řádky) a je-li uvedeno obojí, tak od řádku odpovídajícímu
Začátek
se budou aplikovat instrukce a od řádku
odpovídajícímu Konec
se aplikovat přestanou.
Níže jsou uvedeny některé Instrukce
a jejich
Argumenty
.
s/vzorek/náhrada/příznaky
- nahradí první nalezený
vzorek náhradou
. Příznaky
:
n
- nahradí n-tý výskyt vzorku
(1 až 512),
g
- nahradí všechny výskyty vzorku.w soubor
- do souboru uloží vstupní řádek (řádky)r soubor
- soubor načte do vstupup
- vypíše vstupní řádek na výstupn
- přesune se na další vstupní řádekd
- vstupní řádek je smazány/původní znaky/nové znaky/
- přeloží znaky
(man tr
):
- označí řádek skriptu pro odskok
Instrukcí t
nebo b
t
- byla-li provedena substituce, skočí na následující
značku :
, není-li uvedena, skočí
na konec skriptu{}
- zajistí aplikaci více příkazů na jednu adresu
$ cat ./retezce.txt | sed '2,$s/a/?/g' abclinuxu ?lf? ??? ?bc?bc?bc zn?k $ ?1? ?A? $ cat ./retezce.txt | sed -n '2p' alfa $ cat ./retezce.txt | sed -n '1{ > n > p > }' alfa $ cat ./retezce.txt | sed '2p > d' alfa $ cat ./retezce.txt | sed '4y/a/?/ > 4!d' ?bc?bc?bc |
Na závěr uvedu ještě jeden příklad ve formě skriptu
sed.sh
.
#!/bin/bash spojka="je bydliště" cat <<EOF | sed \ "s/^\(.\+j\) \(.\+\)o:\(.\+\)\$/\3 $s \1e \2a/ t s/^\(.\+j\) \(.\+\):\(.\+\)\$/\3 $s \1e \2a/ t s/^\(.\+\) \(.\+\)o:\(.\+\)\$/\3 $s \1a \2a/ t s/^\(.\+\) \(.\+\):\(.\+\)\$/\3 $s \1a \2a/" Petr Novák:Praha Viktor Igo:Brno Blažej Vodník:Plzeň Jan Hugo:Hradec Králové Metoděj Sporák:Ostrava EOF exit 0 |
Výstup skriptu vypadá následovně.
$ ./sed.sh Praha je bydliště Petra Nováka Brno je bydliště Viktora Iga Plzeň je bydliště Blažeje Vodníka Hradec Králové je bydliště Jana Huga Ostrava je bydliště Metoděje Sporáka |
V případě, že bychom chtěli zajistit správné skloňování úplně pro všechny jména a přijmení, určitě by výše uvedené řešení nebylo to nejkratší a nejvhodnější, berte ho pouze jako ukázku.
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.