FLOSS Manuals

 English |  Español |  Français |  Italiano |  Português |  Русский |  Shqip

Komentorivin perusteet

Säännölliset lausekkeet

Säännölliset lausekkeet

Kun yrität etsiä tekstiä tiedostoista tai muuttaa tekstiä, tarvitset usein epämääräisiä tai monimielisiä hakulausekkeita. Tyypillisiä hakuja ovat:

  • Epämääräisen asioiden joukon löytäminen, kuten "yksi tai useampi nolla".
  • Tekstistä on erilaisia vaihtoehtoja, kuten "väri" ja "värit" tai "rotta" ja "rotan".
  • Tietyn hahmon muodostaman tekstin osan erottaminen. Esimerkiksi sinulla voi olla lista sähköpostiosoitteita, kuten joku@fsf.org tai joku@flossmanuals.net, ja tahdot erottaa sen osan, joka on @ -merkin jälkeen (fsf.org ja flossmanuals.net).

Etsiäksesi tällaisia merkkijonoja ja tehdäksesi niihin muutoksia, erityinen kieli, jota kutsutaan säännöllisiksi lausekkeiksi (englanniksi "regular expressions"), on todella hyödyllinen. Tämä osa tarjoaa nopean esittelyn säännöllisistä lausekkeista. Tämä kieli voi olla hieman uhkaava aluksi -  mutta se ei ole monimutkainen, ainoastaan merkkien käytön kanssa tulee olla hyvin tarkkana. Sinun täytyy käyttää sitä jonkin aikaa, jotta aivosi tottuvat erilaisten säännöllisten lausekkeiden lukemiseen. 

Helpoin tapa oppia ja harjoitella säännöllisiä lausekkeita on käyttää yksinkertaisia suodattimia, jotka tarjotaan komentotulkissa, kuten grep, Sed ja AWK. Komento grep on nähty jo muutamia kertoja tässä kirjassa. Tässä osassa käytämme "laajennettua" versiota, joka on nimeltään egrep, koska se tarjoaa enemmän ominaisuuksia, joita ihmiset käyttävät usein säännöllisissä lausekkeissa. Sed ja AWK esiteltiin aiemmissa luvuissa; käytämme tässä luvussa paljon Sediä.

Tämän osan loppuun mennessä ymmärrät komennot grep, egrep ja Sed melko hyvin. Voit sen jälkeen siirtyä eteenpäin ja käyttää säännöllisiä lausekkeita muissa tilanteissa, joissa ne ovat vieläkin tehokkaampia. Lähes jokaisessa nykyaikaisessa ohjelmointikielessä, joihin sisältyvät muut tässä oppaassa mainitut skriptauskielet Perl, Python ja Ruby, tarjotaan säännöllisiä lausekkeita. Jopa tietokannat tarjoavat säännöllisiä lausekkeita jossain muodossa.

Säännöllisten lausekkeiden yksityiskohdat vaihtelevat työkalusta toiseen, ja jopa työkalun yhdestä versiosta toiseen. Näytämme hyvin yleiset ominaisuudet, mutta ne eivät toimi hyvin kaikissa työkaluissa.

Pelkkä teksti

Säännöllisen lausekkeen ei tarvitse olla hieno. Tähän asti esittelemämme grep-komennot etsivät pelkkää tekstiä:

$ cat color_file
Primary colors blue and red make the color magenta
Primary colors blue and green make the colour cyan
Primary colors red and green make the colour yellow
Black and white make grey
$ grep 'colour' color_file
Primary colors blue and green make the colour cyan
Primary colors red and green make the colour yellow

Koska sanassa "colour" ei ole ohjausmerkkejä, jotka komentotulkki voisi tulkita, emme tarvitse heittomerkkejä, mutta käytämme niitä saadaksemme tavan iskostettua. Tässä luvussa käsitellyt egrep -komennot käyttävät paljon ohjausmerkkejä.

Määrittelemättömät joukot

Yksi säännöllisten lausekkeiden yksinkertainen käyttötapa on etsiä "mikä tahansa määrä" jotain, tai sumea joukko, kuten "3-5" väliviivaa. Tässä ovat tätä tukevat ohjausmerkit. Yksinkertaisuuden vuoksi näytämme ne ensin erikseen, jonka jälkeen käytämme niitä joissain työkaluissa.

Sovita nolla tai useampi kappale merkkijonoa X  X*
Sovita yksi tai useampi kappale merkkijonoa X  X+
Sovita nollasta yhteen kappaletta merkkijonoa X  X?
Sovita 3-5 kappaletta merkkijonoa X  X{3,5}

Nämä muistuttavat paljon komentotulkin ohjausmerkkejä, mutta niissä on pieniä eroja. Keskity niiden merkitykseen säännöllisissä lausekkeissa, ja ota huomioon, että se tosiaan on komentotulkin ohjausmerkeistä eroava kieli.

Nyt voimme nähdä, kuinka voimme löytää sekä merkkijonot "color" että "colour" yhdessä haussa. Tarvitsemme joko 0 tai 1 kappaletta merkkiä "u", joten määritämme:

$ egrep 'colou?r' color_file
Primary colors blue and red make the color magenta
Primary colors blue and green make the colour cyan
Primary colors red and green make the colour yellow

Asteriski (*) on yksi yleisimmistä ja hyödyllisimmistä merkeistä säännöllisissä lausekkeissa, mutta se on myös yksi hämmentävimmistä ja väärinkäytetyimmistä. Oleta, että tahdot poistaa kaikki nollat riviltä. Voisit yrittää poistaa "minkä tahansa joukon nollia" asteriskilla: 

$ echo "There are 40006 items" | sed "s/0*/X/"

Ulostuo on kuitenkin:

XThere are 40006 items

Tämä tapahtui, koska Sed korvaa vaatimasi hahmon ensimmäisen tapauksen. Pyydit "nolla tai enemmän" ja tällainen tapaus on heti rivin alussa!

Käytä tässä tapauksessa plus-merkkiä (0+), mutta monet Sedin versiot eivät tue sitä. Voit kiertää tämän rajoituksen näin:  

$ echo "There are 40006 items" | sed "s/00*/X/"
There are 4X6 items

Jos laitat yhden merkin aaltosulkuihin, esimerkiksi {3}, se merkitsee "korvaa tämä numero tarkalleen". Jos lisäät mukaan pilkun ilman toista merkkiä {3,}, se merkitsee "sovita mikä tahansa numero, joka on kolme tai enemmän." 

Määrittämättömät sovitukset, luokat ja kantamat

Sovittaaksesi mitä tahansa merkkiä, voit käyttää pistettä (.). Niinpä seuraava sopii kauttaviivaan, jota seuraa mikä tahansa merkki ja toinen kauttaviiva:

$ egrep '/./' file

Pistettä seuraa yleensä yksi sumeista määritteistä edellisestä kappaleesta. Niinpä seuraavat sopivat mihin tahansa merkkeihin kauttaviivojen välissä (merkkejä täytyy kuitenkin olla ainakin yksi):

$ egrep '/.+/' file

Seuraava on sama, mutta se löytää myös rivejä, joissa on kaksi kauttaviivaa peräkkäin (//):

$ egrep '/.*/' file

Piste on yleinen merkki tekstissä, joten tahdot usein pisteen merkitsevän pistettä - jotta sillä ei ole erikoista ohjausmerkin merkitystään. Kun tahdot etsiä merkkiä, jota työkalusi pitävät ohjausmerkkinä, laita sen eteen kenoviiva (\):

$ egrep '\.' file

Tämä komento löytää vain pisteen. Koska kenoviivan vuoksi piste pakenee ohjausmerkin tilasta, puhumme merkkien paosta kenoviivan avulla.

Jos etsit merkkijonoja, joissa on välimerkkejä etkä tahdo mitään välimerkkejä kohdeltavan ohjamerkkeinä, voi olla väsyttävää ja vaikeaa päästää jokainen merkki pakoon. Harkitse komennon fgrep käyttöä näille merkkijonoille komentojen grep tai egrep sijasta. Komento fgrep ei käsittele mitään ohjausmerkkinä. Sinun täytyy edelleenkin käyttää heittomerkkejä, jotta komentotulkki ei käsittele mitään ohjausmerkkinä.

Hakasulut antavat sinun määritellä merkkiyhdistelmiä. Etsiäksesi sekä sanoja "gray" että "grey", voit määritellä: 

$ egrep "gr[ae]y" color_file
Black and white make grey

Sovittaaksesi englannin vokaaleina usein käytettyjä merkkejä, voit kirjoittaa:

[aeiouy]

Merkkien järjestys ei koskaan merkitse hakasulkujen sisällä. Voimme löytää vokaalittomia rivejä antamalla säännöllisen lausekkeen komennolle egrep. Aloitammme sekavalla tiedostolla, jonka nimi on letter_file:

This is readable text.
Ths s grbg txt.
This is more readable text.
aaaai

Huomaa, että toisella rivillä ei ole vokaaleja, mutta viimeisellä rivillä on pelkästään vokaaleja. Ensin etsimme vokaalia: 

$ grep '[eauoi]' letter_file
This is readable text.
This is more readable text.
aaaai 

Rivi ilman vokaaleja ei sovitu. 

Kokeillaanpa nyt merkkejä, jotka eivät ole vokaaleja. Tämä ei merkitse pelkästään konsonantteja, mutta myös pisteitä ja välilyöntejä. Voimme kääntää merkit ylösalaisin laittamalla tarkemerkin (^) merkkien eteen. Merkkiluokassa (ja ei missään muualla) tarke merkitsee "kaikki paitsi seuraavat". Teemme sen tässä viidellä vokaalilla (sallimme merkin "y" tulla sovitetuksi, koska se voi olla myös konsonantti):

$ grep '[^eauoi]' letter_file
This is readable text.
Ths s grbg txt.
This is more readable text.

Tällä kertaa ainoastaan viimeinen rivi jätettiin pois, koska siinä oli vokaaleita eikä mitään muuta.

Merkkien luokassa voi olla myös merkkien kantamia, minkä osoitat laittamalla väliviivan kahden merkin väliin. Merkinnän [0123] sijasta voit kirjoittaa [0-3]. Ihmiset käyttävät usein seuraavia yhdistelmiä: 

Mikä tahansa numero  [0-9]
Mikä tahansa pieni kirjain  [a-z]
Mikä tahansa suuri kirjain  [A-Z]
Mikä tahansa kirjain  [a-zA-Z]

Kuten taulukon viimeinen esimerkki osoittaa, voit yhdistää merkkien kantamia hakasulkujen sisällä. Voit jopa yhdistää merkkien kantamia muiden merkkien kanssa, kuten seuraavassa kirjaimien ja välimerkkien yhdistelmässä:

[a-zA-Z.,!?]

Emme joutuneet päästämään pistettä pakoon tässä esimerkissä, koska sitä ei käsitellä ohjausmerkkinä hakasulkujen sisällä. 

Huomaa että merkkiluokka, olipa se miten iso tahansa, sopii aina yhteen merkkiin. Jos tahdot sen sopivan moniin merkkeihin, käytä yhtä edellisen osan määrityksistä:

$ egrep '\([a-zA-Z.,!?]+\)' file

Tämä sopii sulkuihin, joiden sisällä on mikä tahansa joukko merkkejä. Meidän täytyi päästää sulut pakoon, sillä ne ovat ohjausmerkkejä - hyvin erityisiä ohjausmerkkejä. Katsomme niitä seuraavaksi. 

Ryhmät

Sulut antavat sinun käsitellä monia merkkejä samaan aikaan. Muista että merkkiluokat hakasulkujen sisällä sopivat aina yhteen merkkiin, vaikka yksi merkki voi olla monta erilaista asiaa. Sen sijaan ryhmät voivat sopia merkkisarjaan. Jos esimerkiksi tahdot sovittaa tuhannen, miljoonan, miljardin tai biljoonan lukumääriä, voit sovittaa:

1,000

1,000,000

1,000,000,000

jne.

Voit tehdä tämän laittamalla ryhmään merkkijonon ",000" ryhmään, sulkien sen sulkuihin. Nyt mikä tahansa siihen käyttämäsi - kuten + -merkki - sovittuu koko ryhmään:

$ egrep '1(,000)+' file

Sulut tekevät vielä enemmän. Ne tallentavat sen mitä löytävät, mitä kutsutaan kaappaukseksi. Sen jälkeen voit viitata siihen myöhemmin. 

Tämä on vaikeasti hahmotettava ominaisuus. Esitelläänpä sitä katsomalla tiedostoa, joka toistaa joitain merkkijaksoja: 

This bell is a tam-tam.
This sentence doesn't appear in the egrep-generated output.
I want it quick-quick.

Ensimmäinen rivi sisältää sanan "tam", väliviivan ja sitten taas sanan "tam". Kolmas rivi sisältää sanan "quick", väliviivan, ja sen jälkeen taas sanan "quick". Näillä riveillä ei itse asiassa ole yhteisiä merkkijonoja, paitsi väliviiva (joka näkyy myös toisella rivillä, joten sen etsiminen ei erota ensimmäistä ja kolmasta riviä toisesta). Ensimmäisen ja kolmannen rivin yhteinen tekijä on hahmo: sana, jota seuraa väliviiva ja se itse. Niinpä voimme ottaa nuo kaksi riviä kaappaamalla sanan ja toistamalla sen (tiedoston nimi doubles):

$ egrep ' ([a-z]+)-\1' doubles
This bell is a tam-tam.
I want it quick-quick.

 

Hämmentävää? Tämä säännöllinen lauseke purettuna osiin:

 ( Aloita ryhmä
 [a-z]+ Mikä tahansa kirjainjoukko (yksi tai enemmän)
 ) Sulje ryhmä
 - Väliviiva (yksinkertainen sovitus)
 \1 Toista aiemmin kaapattu ryhmä

Merkki \1 on erikoissyntaksi, jonka tunnistavat työkalut, jotka antavat sulkeiden kaapata tekstiä. Ensimmäisellä tiedostojen rivillä se sopii merkkijonoon "tam", koska siihen merkit [a-z]+ sopivat. Kolmannella rivillä se sopii merkkijonoon "quick", koska siihen merkit [a-z]+ sopivat. Se sanoo "mitä tahansa löytyykin, tahdon sen uudelleen."

Erottaaksesi sähköpostiosoitteen toisen osan, esimerkiksi merkkijonon "fsf.org" osoitteesta "someone@fsf.org", käytä säännöllistä lauseketta, kuten: 

([a-z._]+)@([a-z._]+)

Tässä tapauksessa \1 sopii osaan ennen merkkiä @, kun taas \2 sopii osaan merkin @ jälkeen. Yritä siis erottaa \2 saadaksesi merkkijonon "fsf.org".

Erottelu

Näimme että merkkiluokat sopivat vain yhteen merkkiin samaan aikaan. Jos sinulla on kaksi tai useampia merkkijaksoja jotka voivat olla samassa paikassa, voit määritellä ne erottelun avulla. Tämä tehdään erottamalla ne pystyviivalla (|). Niinpä seuraava löytää sekä tapauksen "FSF" että tapauksen "Free Software Foundation":

FSF|Free Software Foundation

Voit laittaa erotteluun niin monta vaihtoehtoa kuin tahdot:

gnu.org|FSF|Free Software Foundation

Koska vaihtoehdot on yleensä laitettu suuremman säännöllisen lausekkeen sisään, joudut yleensä laittamaan ne sulkuihin osoittaaksesi niiden alun ja lopun:

The (FSF|Free Software Foundation)

Ankkurointi

Jos tahdot sovittaa jotain sen ilmaantuessa rivin alussa, mutta ei missään muualla, laita säännölliseen lausekkeeseen tarke (^). Näin voit käyttää seuraavaa ottamaan kiinni rivit, jotka alkavat pienellä merkillä:

^[a-z]

Tällä tarkkeen käytöllä ei ole mitään tekemistä sen tarkkeen kanssa, jonka näimme aikaisemmin hakasulkujen sisällä. Tarke merkitsee "rivin alussa" kun se on säännöllisen lausekkeen ensimmäinen ilmaus, mutta vain siinä sijainnissa. 

Vastaavasti voit sovittaa jotain rivin lopussa lisäämällä dollarimerkin ($) säännöllisen lausekkeen loppuun:

[0-9]$

Lauseessa "I added 3 and 5 to make 8" edellinen säännöllinen lauseke tulee sopimaan numeroon 8, koska se on rivin lopussa.

Kun etsit rivejä, jotka sopivat säännölliseen lausekkeeseen tarkasti (ei erillistä testiä alussa eikä lopussa), käytä molempia ankkureita. Jos tahdot varmistaa, että rivissä on vain numeroita, kirjoita:

^[0-9]+$

Merkit [0-9]+ tarkoittavat "yksi tai enemmän numeroita" ja merkit ^ ja $ varmistavat, että säännöllinen lauseke ottaa koko rivin.

Tahdoimme näyttää sinulle mitä säännöllisillä lausekkeilla voi saada aikaan. On paljon enemmän mahdollisuuksia, joista jotkin ovat käytännöllisiä vain ohjelmointikielissä. Kuten aiemmin varoitimme, eri työkalut tukevat eri ominaisuuksia, joten joudut lukemaan dokumentaation egrepille, Sedille tai mille tahansa muulle käyttämällesi työkalulle tai kielelle saadaksesi selville mikä toimii.

Kun testaat säännöllisiä lausekkeita, voit kokeilla monia verkossa olevia tai painettuja kirjoja (joista jotkin ovat ilmaisia ja jotkin maksullisia) jotka auttavat ratkaisemaan ongelmia, kuten väärin käytettyjä hakasulkuja tai sulkuja. Sellaisten työkalujen avulla voit oppia monimutkaisemmat ominaisuudet ja kirjoittaa helpommin monimutkaisia säännöllisiä lausekkeita.

There has been error in communication with Booktype server. Not sure right now where is the problem.

You should refresh this page.