Muokataan sivua Säännöllinen lauseke
Siirry navigaatioon
Siirry hakuun
Kumoaminen voidaan suorittaa. Varmista alla olevasta vertailusta, että haluat saada aikaan tämän lopputuloksen, ja sen jälkeen julkaise alla näkyvät muutokset.
Nykyinen versio | Oma tekstisi | ||
Rivi 1: | Rivi 1: | ||
'''Säännöllinen lauseke''' (engl. '''regular expression''', '''regexp''') on yksinkertainen merkkijonokieli, joka voi joko ''vastata'' tai ''olla vastaamatta'' jotain toista merkkijonoa. Linux- ja Unix-järjestelmissä säännöllisiä | '''Säännöllinen lauseke''' (engl. '''regular expression''', '''regexp''') on yksinkertainen merkkijonokieli, joka voi joko ''vastata'' tai ''olla vastaamatta'' jotain toista merkkijonoa. Linux- ja Unix-järjestelmissä säännöllisiä lauskkeista on suurta hyötyä [[komentorivi]]ä käytettäessä esimerkiksi merkkijonojen etsimis- ja korvaustoiminnoissa. Niiden voidaankin sanoa olevan [[putki]]ttamiseen yhdistettynä tärkeimpiä työkaluja, joita komentorivin edistynyt käyttö edellyttää. | ||
Tässä artikkelissa on esitetty johdatus säännöllisiin lausekkeisiin siten, miten | Tässä artikkelissa on esitetty johdatus säännöllisiin lausekkeisiin siten, miten komentorivityöklu <tt>[[grep]]</tt> ne ymmärtää ''laajennettussa'' (engl. extended) tilassa. Kaikissa säännöllisten lausekkeiden toteutuksissa syntaksi ei kuitenkaan ole aivan sama. Perusoperaattorit (<tt>*</tt>, <tt>+</tt>, <tt>?</tt>, sulut) ovat kuitenkin ''universaaleja'', eli kaikki toteutukset tukevat niitä. | ||
Säännöllisistä lausekkeista on yleisesti käytössä kolme tyyppiä: ''tavallinen'' (engl. basic), ''laajennettu ''(engl. extended) ja ''[[Perl]]-tyyppinen''. Tässä ohjeessa esitetty syntaksi on yhteensopiva Linuxin [[GNU]]-grepin laajennetun syntaksin kanssa jollei toisin mainita | Säännöllisistä lausekkeista on yleisesti käytössä kolme tyyppiä: ''tavallinen'' (engl. basic), ''laajennettu ''(engl. extended) ja ''[[Perl]]-tyyppinen''. Varsinkin useassa järjestelmässä käytettäviä [[skripti|skriptejä]] kirjoitettaessa täytyy olla huolellinen, mikäli käyttää tavallisesta poikkeavia ilmaisuja. Tässä ohjeessa esitetty syntaksi on yhteensopiva Linuxin [[GNU]]-grepin laajennetun syntaksin kanssa jollei toisin mainita. | ||
Säännöllisiä lausekkeita ei | Säännöllisiä lausekkeita ei pidä sekoittaa tiedostonimi-jokereihin ([[glob]]), joilla on samankaltainen toiminnallisuus (vrt. <tt>*</tt> ja <tt>.*</tt>). | ||
== Teoriaa == | == Teoriaa == | ||
[[wikipedia:fi:Tietojenkäsittelytiede|Tietojenkäsittelytieteessä]] | [[wikipedia:fi:Tietojenkäsittelytiede|Tietojenkäsittelytieteessä]] säännölliset lausekkeet ymmärrettään [[wikipedia:fi:säännöllinen kieli|säännöllisestä kielena]], joka voidaan tunnistaa [[wikipedia:fi:äärellinen automaatti|äärellisellä automaatilla]]. Säännöllisten lauskkeiden historia juontaa juurensa siten 50- ja 60-luvuille tietojenkäsittelytieteen syntyaikohiin. | ||
Säännöllisiä lausekkeita voi hyödyntää monissa ohjelmointikielissä (mm. Perl, Java, Python, ECMAScript). Mille tahansa [[wikipedia:en:Turing complete|Turing-täydelliselle]] ohjelmointikielelle voidaan myös aina kirjoittaa säännöllisten lausekkeiden [[wikipedia:fi:Ohjelmointikielen tulkki|tulkki]]. | Säännöllisiä lausekkeita voi hyödyntää monissa ohjelmointikielissä (mm. Perl, Java, Python, ECMAScript). Mille tahansa [[wikipedia:en:Turing complete|Turing-täydelliselle]] ohjelmointikielelle voidaan myös aina kirjoittaa säännöllisten lausekkeiden [[wikipedia:fi:Ohjelmointikielen tulkki|tulkki]]. | ||
Rivi 27: | Rivi 27: | ||
bono | bono | ||
Yleensä (mm. grep ja awk) katsotaan, että kohteen alussa ja lopussa voi olla mielivaltainen määrä ei-vastaavia merkkejä. Tällöin kohde ( | Yleensä (mm. grep ja awk) katsotaan, että kohteen alussa ja lopussa voi olla mielivaltainen määrä ei-vastaavia merkkejä. Tällöin kohde (s.o. näiden komentojen tapauksessa ''rivi'') vastaa lauseketta, jos edes jokin sen ''osa'' vastaa lauseketta. Siis grep ja awk -yhteydessä lauseke | ||
abba | abba | ||
vastaa kohdetta | vastaa kohdetta | ||
Rivi 69: | Rivi 69: | ||
bba | bba | ||
Todettakooon, että selvästi b-merkkien määrä kohteessa voi olla mielivaltainen, joten eri vastaavia kohdemerkkijonoja on olemassa myös ääretön määrä. | |||
=====Vähintään yksi: <tt>+</tt>===== | =====Vähintään yksi: <tt>+</tt>===== | ||
Rivi 83: | Rivi 83: | ||
'''a'''cccca | '''a'''cccca | ||
bba | bba | ||
=====Ehdollinen: <tt>?</tt>===== | =====Ehdollinen: <tt>?</tt>===== | ||
Rivi 118: | Rivi 116: | ||
tarkoittaa ''"korkeintaan m kertaa"''. | tarkoittaa ''"korkeintaan m kertaa"''. | ||
Sivuhuomatuksena todettakoon, että yllä olevan perusteella lyhyemmät operaattorit <tt>*</tt>, <tt>+</tt> ja <tt>?</tt> voitaisiin aina korvata ilmaisuilla <tt>{0,}</tt>, <tt>{1,}</tt> ja <tt>{0,1}</tt> vastaavasti. {m,n}-muoto on kuitenkin uudempi laajennos, joka ei toimi kaikissa ohjelmassa. | |||
'''Huom!''' Operaattori <tt>{n,m}</tt> ei ole tuettu kaikissa säännöllisten lausekkeiden toteutuksissa. GNU grep tukee niitä laajennetussa tilassa (<tt>egrep</tt>). | '''Huom!''' Operaattori <tt>{n,m}</tt> ei ole tuettu kaikissa säännöllisten lausekkeiden toteutuksissa. GNU grep tukee niitä laajennetussa tilassa (<tt>egrep</tt>). | ||
Rivi 138: | Rivi 136: | ||
'''hu'''aa!! | '''hu'''aa!! | ||
'''hu'''uuurraa!! | '''hu'''uuurraa!! | ||
'''hurr'''urrur!! | '''hurr'''urrur!! | ||
jne. | jne. | ||
Rivi 263: | Rivi 261: | ||
[thlTHL]upu | [thlTHL]upu | ||
Hakasulkujen välissä voidaan myös määritellä [[lokaali]]n | Hakasulkujen välissä voidaan myös määritellä [[lokaali]]n aakkoston mukaisia välejä väliviivalla <tt>-</tt>. Tällöin | ||
19[4-9][0-9]|20[0-9][0-9] | 19[4-9][0-9]|20[0-9][0-9] | ||
vastaa kaikkia vuosilukuja välillä 1940-2099. Samoin | vastaa kaikkia vuosilukuja välillä 1940-2099. Samoin | ||
Rivi 277: | Rivi 275: | ||
'''Osasto '''J | '''Osasto '''J | ||
On huomioitavaa, että myös kohteet ”Osasto b” tai ”Osasto È” saattavat vastata yllä esitettyä | On huomioitavaa, että myös kohteet ”Osasto b” tai ”Osasto È” saattavat vastata yllä esitettyä lausketta joissain [[lokaali|lokaaleissa]]. | ||
Jos merkki <tt>-</tt> halutaan sisällyttää hakasulkuilmaisuun, se jätetään viimeiseksi. Esim. | Jos merkki <tt>-</tt> halutaan sisällyttää hakasulkuilmaisuun, se jätetään viimeiseksi. Esim. | ||
Rivi 297: | Rivi 295: | ||
zo | zo | ||
Hakasulkuilmaisusn merkitys voidaan kääntää asettamalla hattu <tt>^</tt> sen ensimmäiseksi merkiksi. Tällöin hakasulkuilmaisu vastaa mitä tahansa hakasuluissa <u>'''ei'''</u> esiintyvää merkkiä kohteessa. Täten lauseke | |||
[^aeiouyåäö]+ | [^aeiouyåäö]+ | ||
vastaa mitä tahansa pelkistä konsonanteista, välimerkeistä ja numeroista koostuvaa kohdetta, kuten | vastaa mitä tahansa pelkistä konsonanteista, välimerkeistä ja numeroista koostuvaa kohdetta, kuten | ||
Rivi 322: | Rivi 320: | ||
Merkkiluokat tulee laittaa lisäksi ulompien hakasulkujen <tt>[]</tt> sisään. Esimerkiksi | Merkkiluokat tulee laittaa lisäksi ulompien hakasulkujen <tt>[]</tt> sisään. Esimerkiksi | ||
<nowiki>[[:upper:]]</nowiki>+ | <nowiki>[[:upper:]]</nowiki>+ | ||
joka vastaa | joka vastaa yleensä ilmaisua | ||
[A-Z]+ | [A-Z]+ | ||
eli mielivaltainen (vähintään yksi) määrä isoja kirjaimia A-Z. | eli mielivaltainen (vähintään yksi) määrä isoja kirjaimia A-Z. | ||
Rivi 350: | Rivi 348: | ||
=== Rivin alku ja loppu: <tt>^</tt> ja <tt>$</tt>=== | === Rivin alku ja loppu: <tt>^</tt> ja <tt>$</tt>=== | ||
On voinut herätä kysymys, kuinka voidaan vastata kohdetta ( | On voinut herätä kysymys, kuinka voidaan vastata kohdetta (s.o. riviä) ''tarkalleen''. Heti alussa selvisi, että esim grepin mielestä kohde (rivi) vastaa lauseketta, jos lauseke esiintyy missä tahansa kohdassa riviä. Jos halutaan, että lauseke vastaa alusta loppuun tarkalleen koko riviä, on otettava käyttöön erikoismerkit <tt>^</tt> ja <tt>$</tt>. Nämä vastaavat kohteessa rivin tai merkkijonon alkua ja loppua kuvaavia "näkymättömiä" merkkejä vastaavasti. Siten | ||
^abba$ | ^abba$ | ||
vastaa vain riviä | vastaa vain riviä | ||
Rivi 390: | Rivi 388: | ||
(... jne ...) | (... jne ...) | ||
Jos haluamme ylläolevasta listasta vain "qmail" -alkuisten [[käyttäjä|käyttäjien]] prosessit, voisimme | Jos haluamme ylläolevasta listasta vain "qmail" -alkuisten [[käyttäjä|käyttäjien]] prosessit, voisimme kirjoittaa | ||
ps -ef | grep qmail | ps -ef | grep qmail | ||
Tämä kuitenkin tulostaa myös kaikki sellaiset prosessit, joiden nimikentässä esiintyy "qmail" – joukossa myös käyttäjän [[root]] prosesseja vastoin alkuperäistä tarkoitusta: | Tämä kuitenkin tulostaa myös kaikki sellaiset prosessit, joiden nimikentässä esiintyy "qmail" – joukossa myös käyttäjän [[root]] prosesseja vastoin alkuperäistä tarkoitusta: | ||
$ ps -ef | grep qmail | $ ps -ef | grep qmail | ||
'''qmail'''s 3986 1 0 Jan21 ? 00:00:00 qmail-send | '''qmail'''s 3986 1 0 Jan21 ? 00:00:00 '''qmail'''-send | ||
'''qmail'''l 3990 3986 0 Jan21 ? 00:00:00 splogger qmail 2 | '''qmail'''l 3990 3986 0 Jan21 ? 00:00:00 splogger '''qmail''' 2 | ||
root 3993 3986 0 Jan21 ? 00:00:00 '''qmail'''-lspawn | /usr/bin/deliverquota ./Maildir | root 3993 3986 0 Jan21 ? 00:00:00 '''qmail'''-lspawn | /usr/bin/deliverquota ./Maildir | ||
'''qmail'''r 3994 3986 0 Jan21 ? 00:00:00 qmail-rspawn | '''qmail'''r 3994 3986 0 Jan21 ? 00:00:00 '''qmail'''-rspawn | ||
'''qmail'''q 3995 3986 0 Jan21 ? 00:00:00 qmail-clean | '''qmail'''q 3995 3986 0 Jan21 ? 00:00:00 '''qmail'''-clean | ||
Ratkaisu qmail -alkuisten käyttäjien prosessien listaamiseen on: | Ratkaisu qmail -alkuisten käyttäjien prosessien listaamiseen on: | ||
Rivi 410: | Rivi 408: | ||
===== Pako komentotulkista ===== | ===== Pako komentotulkista ===== | ||
Jos halutaan antaa jokin monimutkaisempi ilmaisu, on hyvä asettaa säännöllinen lauseke yksinkertaisten heittomerkkien <tt>'</tt> sisään, jotta ne regexp-operaattorit, joillla on jokin erikoismerkitys [[komentotulkki| | Jos halutaan antaa jokin monimutkaisempi ilmaisu, on hyvä asettaa säännöllinen lauseke yksinkertaisten heittomerkkien <tt>'</tt> sisään, jotta ne regexp-operaattorit, joillla on jokin erikoismerkitys [[komentotulkki|komeotulkissa]] eivät aiheuta ongelmia. | ||
$ echo moi | egrep m(o|a)i | $ echo moi | egrep m(o|a)i | ||
-bash: syntax error near unexpected token `(' | -bash: syntax error near unexpected token `(' | ||
Rivi 418: | Rivi 416: | ||
===== Laajennetut säännölliset lausekkeet: egrep ===== | ===== Laajennetut säännölliset lausekkeet: egrep ===== | ||
Esimerkissä käytettiin komentoa <tt>egrep</tt>. Se on oikopolku grepin [[valitsin|valitsimelle]] <tt>-E</tt>, joka ottaa säännöllisten lausekkeiden laajennetun (engl. extended) tuen käyttöön. Normaalissa käytössä (pelkkä komento <tt>grep</tt>) operaattorit <tt>? + {} | (</tt> ja <tt>)</tt> eivät ole käytettävissä, paitsi asettamalla niiden eteen pako-operaattorin <tt>\</tt> | Esimerkissä käytettiin komentoa <tt>egrep</tt>. Se on oikopolku grepin [[valitsin|valitsimelle]] <tt>-E</tt>, joka ottaa säännöllisten lausekkeiden laajennetun (engl. extended) tuen käyttöön. Normaalissa käytössä (pelkkä komento <tt>grep</tt>) operaattorit <tt>? + {} | (</tt> ja <tt>)</tt> eivät ole käytettävissä, paitsi asettamalla niiden eteen pako-operaattorin <tt>\</tt>. | ||
===== Prosessoitu tuloste: awk ===== | ===== Prosessoitu tuloste: awk ===== | ||
Rivi 439: | Rivi 437: | ||
== Laajennukset == | == Laajennukset == | ||
Lukuunottamatta operaattoria <tt>{n,m}</tt> ja POSIX-luokkia (<tt>[[:luokka:]]</tt> jne.) yllä esitetty on pitkälti universaalisti tuettua säännöllisten lausekkeiden eri toteutuksissa. Monissa toteutuksissa on kuitenkin tehty laajennuksia tähän, mutta esim. | Lukuunottamatta operaattoria <tt>{n,m}</tt> ja POSIX-luokkia (<tt>[[:luokka:]]</tt> jne.) yllä esitetty on pitkälti universaalisti tuettua säännöllisten lausekkeiden eri toteutuksissa. Monissa toteutuksissa on kuitenkin tehty laajennuksia tähän, mutta esim. [[grep]] ei tue seuraavia. | ||
=== Pakoluokat === | === Pakoluokat === | ||
Rivi 480: | Rivi 478: | ||
*[[wikipedia:fi:pinoautomaatti|Pinoautomaatti]] | *[[wikipedia:fi:pinoautomaatti|Pinoautomaatti]] | ||
*[[wikipedia:fi:turingin kone|Turingin kone]] | *[[wikipedia:fi:turingin kone|Turingin kone]] | ||
*[http://www.ohjelmointiputka.net | *[http://www.ohjelmointiputka.net/opas.php?tunnus=phpsl Säännölliset lausekkeet PHP:ssä] -opas Ohjelmointiputkassa | ||
*[http://swtch.com/~rsc/regexp/regexp1.html Regular Expression Matching Can Be Simple And Fast]: Keskustelua säännöllisten lausekkeiden toteutuksesta C-kielellä englanniksi. | *[http://swtch.com/~rsc/regexp/regexp1.html Regular Expression Matching Can Be Simple And Fast]: Keskustelua säännöllisten lausekkeiden toteutuksesta C-kielellä englanniksi. | ||