Szabályos kifejezések
- Mire jó?
Stringek rugalmas megadására, szöveg kereső, helyettesítő programokban.
Mintákat (pattern) adhatunk meg, és egy-egy mintára való illeszkedéstől függően csinálhatunk vmit az adott
szövegrésszel
- Emlékeztető:
cp /usr/share/pictures/*.xmp ~/pics/
Ez NEM szabályos kifejezés
- Hol használhatjuk?
grep, egrep, sed, awk és újabban bash kifejezésekben "[[ ]]"
- Hol nem működnek?
- fgrep
- filnevek megadásánál (hasonlít a joker karakterekre)
- case elágazásnál (szintén csak "joker szabályok" használhatóak)
- test (vagy [ ]) feltételeknél
Milyen építőelemek (atom) vannak?
c | Egy darab NEM SPECIÁLIS karakter |
. | Egyetlen tetszőleges karakter |
^ | Sor eleje (egész pontosan a sor elején lévő üres string illeszkedik rá) |
$ | Sor vége (a sor végén lévő üres string illeszkedik rá) |
\c | Ha a "c" karakternek vmilyen speciális jelentése van, a \ jel kikapcsolja ezt a speciális jelentést |
[karakterek] | A felsorolt karakterek bármelyike (de csak 1) illeszkedik rá |
[^karakterek] | A NEM felsorolt karakterek bármelyike |
[c1-c2] | c1 és c2 közötti karakterek bármelyike |
Egy zárójelbe tett reguláris kifejezés |
FONTOS: a [ ]-ek belsejében a speciális jelek elvesztik a különleges jelentésüket!
Milyen jelentésmódosító jelek vannak?
atom* | 0 vagy többszöri ismétlődés |
atom+ | Egy vagy többszöri ismétlődés |
atom? | 0 vagy egyszeri ismétlődés |
atom{m} | Pontosan m-szeri ismétlődés |
atom{m,} | Legalább m-szeri ismétlődés |
atom{m,n} | Legalább m-szeri, de legfeljebb n-szeri ismétlődés |
Speciális jelek - összefoglálás
Két csoportra oszthatjuk azokat a jeleket, melyek valamilyen speciális jelentéssel bírnak a szabályos kifejezésekben.
Az első csoportba tartoznak azok a spec. jelek, melyek különleges jelentése alapértelmezésben be van kapcsolva.
Míg a másik csoportba tartozó jelek speciális jelenzésel alapértelmezésben ki van kapcsolva.
- * , . , [ , ] , \ , ^ , $
- { , } , ( , ), | , + , ?
FONTOS:A fenti csoportosítás csak az úgynevezett alap szabályos kifejezések (basic regular expression) esetében érvényesek.
Az ún. kiterjesztett szab. kifejezések (extended reg. expr.) esetében minden speciális jel különleges jelentéses be van kapcsolva
grep
Egy kereső program, mely fileokban (vagy az standard inputjára érkező adatokban) képes keresni bizonyos tulajdonságú sorokat. Ezeket a "tulajdonságokat" adhatjuk meg szabályos kifejezésekkel.
A grep-en kívül használható még az fgrep
(nem kezel szab. kif.-eket) és az egrep
(kiterjesztett. szab. kif.-ek) is.
Példák
cat f1 | grep "36"
cat f1 | grep 36
grep "36" f1
cat f1 | grep "alma"
# Ezekben a példákban használható lett volna az fgrep is
cat f1 | grep "a*" # itt mást jelent a * , mint jokereknél !!
cat f1 | grep 'a*' # ugyanaz, mint a " " esetében
cat f1 | grep 'a\*' # 'a*'-ot keres
cat f1 | grep a* # HIBÁS, mert a *-ot "megeszi" a shell
cat f1 | fgrep "a*" # 'a*'-ot keres!!
ls -la | grep "^d" | wc -l
ls -la | grep "gyak1$"
ls -la | grep "gyak1.txt$"
ls -la | grep "gyak1\.txt$"
cat f1 | grep "^a\*"
cat f1 | grep "a.$"
cat f1 | grep "^.a"
cat f1 | grep "..." # olyan sorok, melyek legalább 3 karakterből állnak
cat f1 | grep "\.$" # sorvégi . karakter
cat f1 | grep "\.\.\." # ... -t tartalmazó sorok
cat f1 | grep "[abc]" # a megadott karakterek bármelyike
cat f1 | grep "^[abc]" # itt a ^ a sor elejét jelenti
cat f1 | grep "[^abc]" # itt pedig tagadást
cat f1 | grep "[0-9]"
cat f1 | grep "[a-zA-Z]"
cat f1 | grep "[A-Z][a-z]"
cat f1 | grep "[^0-9][0-9]"
cat f1 | grep "[]abc]" # Ha megát a ']' jelet is bele akarjuk tenni a tartományba,
# akkor az első helyen kell állnia
cat f1 | grep "[^]abc]"
cat f1 | grep "[A-Za-z_-]" # Ha a '-' jelet is bele akarjuk venni,
# akkor vagy az első vagy az utolsó helyen kell állnia
cat f1 | grep "[-+]" # Itt a '-' az első helyen áll
# a '+' pedig egyszerű karakternek számít, mert [ ] belsejében van!
cat f1 | grep "[.*]" # Vagy '.' vagy '*' karakter
cat f1 | fgrep "[.*]" # Olyan sorok, amelyekben szerepel a '[.*]' string
cat f1 | grep "^a*" # a * előtt lévő kifejezés akárhány (0 is) előfordulása
cat f1 | grep "^a.*"
cat f1 | grep "[0-9].*"
cat f1 | grep "^a\+" # az előtte álló kifejezés legalább egyszeri előfordulása
cat f1 | grep "^a+" # ez így soreleji 'a+'-t keres
cat f1 | grep "^a\?"
#Vigyázzunk!
cat f1 | egrep "^a\+"
cat f1 | egrep "^a+"
cat f1 | grep "\(ab\)\+"
cat f1 | egrep "(ab)+"
cat f1 | grep "\([a-z][0-9]\)*"
cat f1 | grep "\.\{3\}" # PONTOSAN 3 egymástkövető pontot tartalmazó sorok
cat f1 | grep "\.\{4,\}" # LEGALÁBB 4 egymástkövető pont
cat f1 | grep "[0-9]\{3,7\} # LEGALÁBB 3 de LEGFELJEBB 4 számjegy
cat f1 | egrep "asztal(on|ban|hoz|nak)" # csak az egrep tudja
jel=`head -n1 f.txt | cut -c1`
who | cut -d' ' -f1 | grep "^$jel.*a$"
cat f1 | grep -- "-\?28" # Illeszkedik rá a 28 és a -28
cat f1 | grep "\-\?28" # Ugyanaz, csak máshogy megoldva a '-' probléma
cat f1 | grep -- "-\?[0-9]\+" # Pozitív és negatív egész számok
cat f1 | grep "\-\?[0-9]\+"
cat f1 | grep "[12]-[0-9]{6}-[0-9]{4}"
cat f1 | grep "[12]-[0-9]\{6\}-[0-9]\{4\}"
cat f1 | grep "\\" # rossz!!
cat f1 | grep '\\' # jó
cat f1 | grep "^\([a-z]\)\1"
cat f1 | grep "\([0-9]\)\1$"
Egyéb lehetőségek
POSIX Character Classes [[:class:]]
[[:alnum:]] | matches alphabetic or numeric characters. This is equivalent to A-Za-z0-9. |
[[:alpha:]] | matches alphabetic characters. This is equivalent to A-Za-z. |
[[:blank:]] | matches a space or a tab. |
[[:cntrl:]] | matches control characters. |
[[:digit:]] | matches (decimal) digits. This is equivalent to 0-9. |
[[:graph:]] | (graphic printable characters). Matches characters in the range of ASCII 33 - 126. This is the same as [:print:], below, but excluding the space character. |
[[:lower:]] | matches lowercase alphabetic characters. This is equivalent to a-z. |
[[:print:]] | (printable characters). Matches characters in the range of ASCII 32 - 126. This is the same as [:graph:], above, but adding the space character. |
[[:space:]] | matches whitespace characters (space and horizontal tab). |
[[:upper:]] | matches uppercase alphabetic characters. This is equivalent to A-Z. |
[[:xdigit:]] | matches hexadecimal digits. This is equivalent to 0-9A-Fa-f. |
Egy kidolgozott példa
Részlet a Unix/Linux héjprogramozás c. könyvből
grep parancsról részletesen - kapcsolók
- -num:
Az illeszkedést mutató sorok környezetükkel együtt kerülnek az stdout-ra, azaz nem csak az illeszkedő
sort írja ki, hanem az adott sor előtti és utáni num db sort is.
DE: egy sor csak egyszer szerepel, azaz ha átfedések vannak, akkor is egy sor max. egyszer kerül kiírásra
- -A num:
Az illeszkedést mutató sorok UTÁNI num db sor is kiírodik
- -B num:
Az illeszkedést mutató sorok ELŐTTI num db sor is kinyomtatásra kerül
- -c:
Elhagyja a szokásos kimenetet, ehelyett az illeszkedést mutató sorok számát írja ki, minden file esetére
- -e minta:
Megmondjuk neki, hogy most minta(pattern) jön, pl hasznos ha '-' jellel kezdődik a mintánk
- -f fájl:
A mintát a megadott file-ból veszi
- -h:
Több fileból való kereséskor elhagyja a kimenetről a filnevek sor eleji kiírását
- -i:
Nem különbözteti meg a kis -és nagybetűket
- -L:
Elhagyja a szokásos kimenetet és csak azokat a filenekevet írja ki, amelyekben NEM volt(ak) illeszkedő sor(ok)
- -l:
Elhagyja a szokásos kimenetet és csak azokat a filenekevet írja ki, amelyekben volt(ak) illeszkedő sor(ok)
- -v:
Megfordítja az illeszkedés értelmét: azok a sorok kerülnek listázásra, melyek NEM illeszkednek a mintára
- -w:
Csak azokat a sorokat választja ki, amelyekben az illeszkedés teljes szavakból származik
- -x:
Csak teljes sorokkal való illeszkedést vizsgál
sed (Stream EDitor)
- Tulajdonképpen egy nem interaktív programozható szövegszerkesztő/manipuláló program
- Vagy paraméterként várja a feldolgozandó file-t vagy az stdin-ről olvas (mint a grep)
- Ez is sor alapú, mint a grep, azaz egyszerre egy sort olvas be, és ezen hajtja végre a megadott műveleteket
A legegyszerűbb parancs: p (print)
cat f1 | sed 'p'
cat f1 | sed '5p'
cat f1 | sed -n '5p'
cat f1 | sed -n '2,5p' # 2-től az 5-ig sorig!
Törlés: d (delete)
cat f1 | sed '3d'
cat f1 | sed '3,5d'
Csere 0.1: y (transform)
echo "abcdabcdXYZ" | sed 'y/abcd/xyzk/' # eredmény: xyzkxyzkXYZ
Tulajdonképpen ugyanazt csinálja, mint a tr nevű unix parancs, azonban van egy lényeges különbség:
sed-nél, ha az y-t használjuk nem adhatunk meg tartományokat ([a-z]), míg tr-nél igen.
Csere: s (substitute)
Szintaxis
sed 's/mit/mire/módosító'
Mi történik?
A sed végignézi az összes sort (egyenként), és ha talál olyan szövegrészt, ami illeszkedik a 'mit' mintára, lecseréli a 'mire' mintának megfelelő szövegre.
Ha nem adunk meg 'módosító'-t, akkor hibába van több olyan szövegrész is a sorban, amire illeszkedit a 'mit', csak az elsőt cseréli!
sed 's/mit/mire/N' -> Csak az N-edik előfordulást cseréli (minden sorban újrakezdi a számolást)
sed 's/mit/mire/g' -> Az összes előfordulást cserélni
echo "1234567abcde" | sed "s/[a-z]/X/"
echo "1234567abcde" | sed "s/[a-z]\+/X/g" # a várt eredmény: 1234567XXXXX
# a valós: 1234567X
echo "1234567abcde" | sed "s/[a-z]*/X/g" # X1X2X3X4X5X6X7X
echo "1234567abcde" | sed "s/.*/XXX&YYY/" # XXX1234567abcdeYYY
echo "abc1234def" | sed "s/[a-z]\+/X&Y/" # XabcY1234def
echo "abc1234def" | sed "s/[a-z]\+/X&Y/g" # XabcY1234XdefY
echo "1234567abcdef" | sed "s/\([0-9]\+\)\([a-z]\+\)/\2\1/" # abcdef1234567
cat unix1.sh | sed 's/#[^!]\+//' # fontos, hogy most ' ' között van a minta (a ! jel miatt kell)
cat unix1.sh | sed 's/#\([^!]\+\)/\1/'
echo $PATH | sed "s/:/\n/g" | wc -l
proba=`echo $1 | sed "s/[0-9]//g"
if [ "$proba" != "" ] # írható [ ! -z "$proba" ]
then
echo "Az első paraméter hibás"
exit 1
fi
Egy kidolgozott példa
Részlet a Unix/Linux héjprogramozás c. könyvből
Ami a sed-ből kimaradt
Érdekesség I.
Hogyan lehet a grep-pet megkerülve elérni, hogy csak az adott mintára illeszekedő sorokat írjuk ki?
cat f1 | sed -n "/PATTERN/p"
Ahol a PATTERN tetszőleges szabályos kifejezés lehet
Érdekesség II.
Hasonló módon meg tudjuk csinálni grep nélkül azt is, hogy csak azokat a sorokat írjuk ki, amik NEM illeszkednek az adott mintára
cat f1 | sed -n "/PATTERN/d"*
Minden sor elejére beszúrunk egy "> "-t
sed "s/^/> /" f1
Beszúrás: i (insert)
- Be tudunk szúrni egy megadott szöveget minden sor elé
cat f1 | sed "i Hello"
- Ugyanezt megtehetjük bizonyos sorokkal
cat f1 | sed "3i Hello" # Csak a 3. sor elé szúrja be
- Összekombinálva a szűrési lehetőségge
cat f1 | sed "/[0-9]\+/ i A következő sorban szám is van:"
Hozzáfűzés: a (append)
Ugyanazok a lehetőségek mint az előbb, csak itt az adott sor mögé tudunk beszúrni
További sed érdekességek
sed "s/$/EOL/"
sed "s/^[ \t]*//"
sed "s/[ \t]*$//"
sed "s/^[ \t]*//;s/[ \t]*$//"
sed "s/x/$MIRE/$HANYADIK"
sed -r -> Extended RegExp
sed "/PATTERN/! s/foo/bar/g"
sed "$d" -> utsó sor törlése
Lépésenként kidolgozott példa: Írjuk ki a legnagyobb A vagy a betűvel kezdődő filet!
ls -lR [aA]*
ls -lR | grep "^-"
ls -lR | grep "^-" | sed "s/[-rwx]* \+[0-9]\+ [a-z]\+ [a-z]\+ *//"
ls -lR | grep "^-" | sed "s/[-rwx]* \+[0-9]\+ [a-z]\+ [a-z]\+ *//" | cut -d" " -f1,4-
ls -lR | grep "^-" | sed "s/[-rwx]* \+[0-9]\+ [a-z]\+ [a-z]\+ *//" | cut -d" " -f1,4- | grep "[0-9]\+ [Aa].*$"
ls -lR | grep "^-" | sed "s/[-rwx]* \+[0-9]\+ [a-z]\+ [a-z]\+ *//" | cut -d" " -f1,4- | grep "[0-9]\+ [Aa].*$" | sort -n
ls -lR | grep "^-" | sed "s/[-rwx]* \+[0-9]\+ [a-z]\+ [a-z]\+ *//" | cut -d" " -f1,4- | grep "[0-9]\+ [Aa].*$" | sort -n | tail -n1
ls -lR | grep "^-" | sed "s/[-rwx]* \+[0-9]\+ [a-z]\+ [a-z]\+ *//" | cut -d" " -f1,4- | grep "[0-9]\+ [Aa].*$" | sort -n | tail -n1 | cut -d" " -f2-