Tutustu edistyneeseen JavaScript-mallien täsmäytykseen säännöllisillä lausekkeilla. Opi regex-syntaksi, käytännön sovelluksia ja optimointitekniikoita tehokkaan ja vankan koodin luomiseksi.
JavaScript-mallien täsmäytys säännöllisillä lausekkeilla: Kattava opas
Säännölliset lausekkeet (regex) ovat tehokas työkalu mallien täsmäytykseen ja tekstin käsittelyyn JavaScriptissä. Ne antavat kehittäjille mahdollisuuden etsiä, validoida ja muokata merkkijonoja määritettyjen mallien perusteella. Tämä opas tarjoaa kattavan yleiskatsauksen säännöllisiin lausekkeisiin JavaScriptissä, kattaen syntaksin, käytön ja edistyneet tekniikat.
Mitä ovat säännölliset lausekkeet?
Säännöllinen lauseke on merkkijono, joka määrittelee hakumallin. Näitä malleja käytetään merkkijonojen täsmäyttämiseen ja käsittelyyn. Säännöllisiä lausekkeita käytetään laajalti ohjelmoinnissa seuraavanlaisiin tehtäviin:
- Tietojen validointi: Varmistetaan, että käyttäjän syöte vastaa tiettyjä muotoja (esim. sähköpostiosoitteet, puhelinnumerot).
- Tietojen poiminta: Haetaan tiettyjä tietoja tekstistä (esim. päivämäärien, URL-osoitteiden tai hintojen poiminta).
- Etsi ja korvaa: Etsitään ja korvataan tekstiä monimutkaisten mallien perusteella.
- Tekstinkäsittely: Jaetaan, yhdistetään tai muokataan merkkijonoja määritettyjen sääntöjen perusteella.
Säännöllisten lausekkeiden luominen JavaScriptissä
JavaScriptissä säännöllisiä lausekkeita voidaan luoda kahdella tavalla:
- Käyttämällä säännöllisen lausekkeen literaalia: Suljetaan malli vinoviivojen (
/) sisään. - Käyttämällä
RegExp-konstruktoria: LuodaanRegExp-olio, jonka malli on merkkijono.
Esimerkki:
// Säännöllisen lausekkeen literaalin käyttö
const regexLiteral = /hello/;
// RegExp-konstruktorin käyttö
const regexConstructor = new RegExp("hello");
Valinta näiden kahden tavan välillä riippuu siitä, onko malli tiedossa käännösaikana vai luodaanko se dynaamisesti. Käytä literaalimerkintää, kun malli on kiinteä ja tiedossa etukäteen. Käytä konstruktoria, kun malli on rakennettava ohjelmallisesti, erityisesti kun siihen sisällytetään muuttujia.
Regex-syntaksin perusteet
Säännölliset lausekkeet koostuvat merkeistä, jotka edustavat täsmäytettävää mallia. Tässä on joitakin perustavanlaatuisia regex-komponentteja:
- Literaalimerkit: Täsmäävät itse merkkeihin (esim.
/a/täsmää merkkiin 'a'). - Metamerkit: Niillä on erityisiä merkityksiä (esim.
.,^,$,*,+,?,[],{},(),\,|). - Merkkiluokat: Edustavat merkkijoukkoja (esim.
[abc]täsmää 'a', 'b' tai 'c'). - Kvanttorit: Määrittävät, kuinka monta kertaa merkin tai ryhmän tulisi esiintyä (esim.
*,+,?,{n},{n,},{n,m}). - Ankkurit: Täsmäävät sijainteihin merkkijonossa (esim.
^täsmää alkuun,$täsmää loppuun).
Yleiset metamerkit:
.(piste): Täsmää mihin tahansa yhteen merkkiin paitsi rivinvaihtoon.^(caret): Täsmää merkkijonon alkuun.$(dollari): Täsmää merkkijonon loppuun.*(asteriski): Täsmää nollaan tai useampaan edeltävän merkin tai ryhmän esiintymään.+(plus): Täsmää yhteen tai useampaan edeltävän merkin tai ryhmän esiintymään.?(kysymysmerkki): Täsmää nollaan tai yhteen edeltävän merkin tai ryhmän esiintymään. Käytetään valinnaisille merkeille.[](hakasulkeet): Määrittelee merkkiluokan, täsmää mihin tahansa yhteen sulkeiden sisällä olevaan merkkiin.{}(aaltosulkeet): Määrittää täsmättävien esiintymien määrän.{n}täsmää tarkalleen n kertaa,{n,}täsmää n tai useamman kerran,{n,m}täsmää n ja m kerran välillä.()(sulkeet): Ryhmittelee merkkejä yhteen ja kaappaa täsmätyn osajonon.\(kenoviiva): Ohittaa metamerkit, jolloin voit täsmätä ne kirjaimellisesti.|(pystyviiva): Toimii "tai"-operaattorina, täsmäten joko ennen tai jälkeen sitä olevaan lausekkeeseen.
Merkkiluokat:
[abc]: Täsmää mihin tahansa merkeistä a, b tai c.[^abc]: Täsmää mihin tahansa merkkiin, joka *ei* ole a, b tai c.[a-z]: Täsmää mihin tahansa pieneen kirjaimeen a:sta z:aan.[A-Z]: Täsmää mihin tahansa isoon kirjaimeen A:sta Z:aan.[0-9]: Täsmää mihin tahansa numeroon 0:sta 9:ään.[a-zA-Z0-9]: Täsmää mihin tahansa aakkosnumeeriseen merkkiin.\d: Täsmää mihin tahansa numeroon (vastaa[0-9]).\D: Täsmää mihin tahansa ei-numeromerkkiin (vastaa[^0-9]).\w: Täsmää mihin tahansa sanamerkkiin (aakkosnumeerinen plus alaviiva; vastaa[a-zA-Z0-9_]).\W: Täsmää mihin tahansa ei-sanamerkkiin (vastaa[^a-zA-Z0-9_]).\s: Täsmää mihin tahansa välilyöntimerkkiin (välilyönti, sarkain, rivinvaihto jne.).\S: Täsmää mihin tahansa ei-välilyöntimerkkiin.
Kvanttorit:
*: Täsmää edeltävään elementtiin nolla tai useamman kerran. Esimerkiksia*täsmää "", "a", "aa", "aaa" ja niin edelleen.+: Täsmää edeltävään elementtiin yhden tai useamman kerran. Esimerkiksia+täsmää "a", "aa", "aaa", mutta ei "".?: Täsmää edeltävään elementtiin nolla tai yhden kerran. Esimerkiksia?täsmää "" tai "a".{n}: Täsmää edeltävään elementtiin tarkalleen *n* kertaa. Esimerkiksia{3}täsmää "aaa".{n,}: Täsmää edeltävään elementtiin *n* tai useamman kerran. Esimerkiksia{2,}täsmää "aa", "aaa", "aaaa" ja niin edelleen.{n,m}: Täsmää edeltävään elementtiin *n* ja *m* kerran välillä (mukaan lukien). Esimerkiksia{2,4}täsmää "aa", "aaa" tai "aaaa".
Ankkurit:
^: Täsmää merkkijonon alkuun. Esimerkiksi^Hellotäsmää merkkijonoihin, jotka *alkavat* sanalla "Hello".$: Täsmää merkkijonon loppuun. EsimerkiksiWorld$täsmää merkkijonoihin, jotka *päättyvät* sanaan "World".\b: Täsmää sanan rajaan. Tämä on sijainti sanamerkin (\w) ja ei-sanamerkin (\W) välillä tai merkkijonon alussa tai lopussa. Esimerkiksi\bword\btäsmää koko sanaan "word".
Liput (Flags):
Regex-liput muokkaavat säännöllisten lausekkeiden käyttäytymistä. Ne lisätään regex-literaalin loppuun tai annetaan toisena argumenttina RegExp-konstruktorille.
g(global): Täsmää kaikkiin mallin esiintymiin, ei vain ensimmäiseen.i(ignore case): Suorittaa kirjainkoosta riippumattoman täsmäytyksen.m(multiline): Mahdollistaa monirivisen tilan, jossa^ja$täsmäävät kunkin rivin alkuun ja loppuun (eroteltu\n:llä).s(dotAll): Sallii pisteen (.) täsmätä myös rivinvaihtomerkkeihin.u(unicode): Mahdollistaa täyden Unicode-tuen.y(sticky): Täsmää vain regexinlastIndex-ominaisuuden osoittamasta indeksistä.
JavaScriptin Regex-metodit
JavaScript tarjoaa useita metodeja säännöllisten lausekkeiden kanssa työskentelyyn:
test(): Testaa, täsmääkö merkkijono malliin. Palauttaatruetaifalse.exec(): Suorittaa haun täsmäykselle merkkijonossa. Palauttaa taulukon, joka sisältää täsmätyn tekstin ja kaapatut ryhmät, tainulljos täsmäystä ei löydy.match(): Palauttaa taulukon, joka sisältää merkkijonon täsmäytyksen tulokset säännöllistä lauseketta vastaan. Käyttäytyy eri tavallag-lipun kanssa ja ilman sitä.search(): Testaa täsmäystä merkkijonossa. Palauttaa ensimmäisen täsmäyksen indeksin tai -1, jos täsmäystä ei löydy.replace(): Korvaa mallin esiintymät korvaavalla merkkijonolla tai funktiolla, joka palauttaa korvaavan merkkijonon.split(): Jakaa merkkijonon osajonojen taulukkoon säännöllisen lausekkeen perusteella.
Esimerkkejä Regex-metodien käytöstä:
// test()
const regex = /hello/;
const str = "hello world";
console.log(regex.test(str)); // Tuloste: true
// exec()
const regex2 = /hello (\w+)/;
const str2 = "hello world";
const result = regex2.exec(str2);
console.log(result); // Tuloste: ["hello world", "world", index: 0, input: "hello world", groups: undefined]
// match() 'g'-lipulla
const regex3 = /\d+/g; // Täsmää yhteen tai useampaan numeroon globaalisti
const str3 = "There are 123 apples and 456 oranges.";
const matches = str3.match(regex3);
console.log(matches); // Tuloste: ["123", "456"]
// match() ilman 'g'-lippua
const regex4 = /\d+/;
const str4 = "There are 123 apples and 456 oranges.";
const match = str4.match(regex4);
console.log(match); // Tuloste: ["123", index: 11, input: "There are 123 apples and 456 oranges.", groups: undefined]
// search()
const regex5 = /world/;
const str5 = "hello world";
console.log(str5.search(regex5)); // Tuloste: 6
// replace()
const regex6 = /world/;
const str6 = "hello world";
const newStr = str6.replace(regex6, "JavaScript");
console.log(newStr); // Tuloste: hello JavaScript
// replace() funktiolla
const regex7 = /(\d+)-(\d+)-(\d+)/;
const str7 = "Today's date is 2023-10-27";
const newStr2 = str7.replace(regex7, (match, year, month, day) => {
return `${day}/${month}/${year}`;
});
console.log(newStr2); // Tuloste: Today's date is 27/10/2023
// split()
const regex8 = /, /;
const str8 = "apple, banana, cherry";
const arr = str8.split(regex8);
console.log(arr); // Tuloste: ["apple", "banana", "cherry"]
Edistyneet Regex-tekniikat
Kaappausryhmät (Capturing Groups):
Sulkeita () käytetään luomaan kaappausryhmiä säännöllisissä lausekkeissa. Kaappausryhmät antavat sinun poimia tiettyjä osia täsmätystä tekstistä. exec()- ja match()-metodit palauttavat taulukon, jossa ensimmäinen elementti on koko täsmäys ja seuraavat elementit ovat kaapattuja ryhmiä.
const regex = /(\d{4})-(\d{2})-(\d{2})/;
const dateString = "2023-10-27";
const match = regex.exec(dateString);
console.log(match[0]); // Tuloste: 2023-10-27 (Koko täsmäys)
console.log(match[1]); // Tuloste: 2023 (Ensimmäinen kaapattu ryhmä - vuosi)
console.log(match[2]); // Tuloste: 10 (Toinen kaapattu ryhmä - kuukausi)
console.log(match[3]); // Tuloste: 27 (Kolmas kaapattu ryhmä - päivä)
Nimettyt kaappausryhmät:
ES2018 esitteli nimetyt kaappausryhmät, jotka antavat sinun antaa nimiä kaappausryhmille käyttämällä syntaksia (?. Tämä tekee koodista luettavampaa ja ylläpidettävämpää.
const regex = /(?\d{4})-(?\d{2})-(?\d{2})/;
const dateString = "2023-10-27";
const match = regex.exec(dateString);
console.log(match.groups.year); // Tuloste: 2023
console.log(match.groups.month); // Tuloste: 10
console.log(match.groups.day); // Tuloste: 27
Ei-kaappaavat ryhmät:
Jos sinun tarvitsee ryhmitellä regexin osia ilman niiden kaappaamista (esim. soveltaaksesi kvanttoria ryhmään), voit käyttää ei-kaappaavaa ryhmää syntaksilla (?:...). Tämä välttää turhan muistin varaamisen kaapatuille ryhmille.
const regex = /(?:https?:\/\/)?([\w\.]+)/; // Täsmää URL-osoitteeseen, mutta kaappaa vain verkkotunnuksen nimen
const url = "https://www.example.com/path";
const match = regex.exec(url);
console.log(match[1]); // Tuloste: www.example.com
Lookaround-lausekkeet:
Lookaround-lausekkeet ovat nollaleveyksisiä väittämiä, jotka täsmäävät sijaintiin merkkijonossa perustuen malliin, joka edeltää (lookbehind) tai seuraa (lookahead) kyseistä sijaintia, ilman että lookaround-mallia sisällytetään itse täsmäykseen.
- Positiivinen lookahead:
(?=...)Täsmää, jos lookaheadin sisällä oleva malli *seuraa* nykyistä sijaintia. - Negatiivinen lookahead:
(?!...)Täsmää, jos lookaheadin sisällä oleva malli *ei seuraa* nykyistä sijaintia. - Positiivinen lookbehind:
(?<=...)Täsmää, jos lookbehindin sisällä oleva malli *edeltää* nykyistä sijaintia. - Negatiivinen lookbehind:
(? Täsmää, jos lookbehindin sisällä oleva malli *ei edellä* nykyistä sijaintia.
Esimerkki:
// Positiivinen lookahead: Hae hinta vain, kun sitä seuraa USD
const regex = /\d+(?= USD)/;
const text = "The price is 100 USD";
const match = text.match(regex);
console.log(match); // Tuloste: ["100"]
// Negatiivinen lookahead: Hae sana vain, kun sitä ei seuraa numero
const regex2 = /\b\w+\b(?! \d)/;
const text2 = "apple 123 banana orange 456";
const matches = text2.match(regex2);
console.log(matches); // Tuloste: null koska match() palauttaa vain ensimmäisen täsmäyksen ilman 'g'-lippua, mikä ei ole mitä tarvitsemme.
// korjataksesi sen:
const regex3 = /\b\w+\b(?! \d)/g;
const text3 = "apple 123 banana orange 456";
const matches3 = text3.match(regex3);
console.log(matches3); // Tuloste: [ 'banana' ]
// Positiivinen lookbehind: Hae arvo vain, kun sitä edeltää $
const regex4 = /(?<=\$)\d+/;
const text4 = "The price is $200";
const match4 = text4.match(regex4);
console.log(match4); // Tuloste: ["200"]
// Negatiivinen lookbehind: Hae sana vain, kun sitä ei edellä sana 'not'
const regex5 = /(?
Takaisinviittaukset (Backreferences):
Takaisinviittaukset antavat sinun viitata aiemmin kaapattuihin ryhmiin samassa säännöllisessä lausekkeessa. Ne käyttävät syntaksia \1, \2, jne., jossa numero vastaa kaapatun ryhmän numeroa.
const regex = /([a-z]+) \1/;
const text = "hello hello world";
const match = regex.exec(text);
console.log(match); // Tuloste: ["hello hello", "hello", index: 0, input: "hello hello world", groups: undefined]
Säännöllisten lausekkeiden käytännön sovelluksia
Sähköpostiosoitteiden validointi:
Yleinen käyttötapaus säännöllisille lausekkeille on sähköpostiosoitteiden validointi. Vaikka täydellinen sähköpostin validointiregex on erittäin monimutkainen, tässä on yksinkertaistettu esimerkki:
const emailRegex = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/;
console.log(emailRegex.test("test@example.com")); // Tuloste: true
console.log(emailRegex.test("invalid-email")); // Tuloste: false
console.log(emailRegex.test("test@sub.example.co.uk")); // Tuloste: true
URL-osoitteiden poimiminen tekstistä:
Voit käyttää säännöllisiä lausekkeita URL-osoitteiden poimimiseen tekstilohkosta:
const urlRegex = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g;
const text = "Visit our website at https://www.example.com or check out http://blog.example.org.";
const urls = text.match(urlRegex);
console.log(urls); // Tuloste: ["https://www.example.com", "http://blog.example.org"]
CSV-datan jäsentäminen:
Säännöllisiä lausekkeita voidaan käyttää CSV (Comma-Separated Values) -datan jäsentämiseen. Tässä on esimerkki CSV-merkkijonon jakamisesta arvojen taulukkoon, käsitellen lainausmerkeillä varustetut kentät:
const csvString = 'John,Doe,"123, Main St",New York';
const csvRegex = /(?:"([^"]*(?:""[^"]*)*)")|([^,]+)/g; //Korjattu CSV regex
let values = [];
let match;
while (match = csvRegex.exec(csvString)) {
values.push(match[1] ? match[1].replace(/""/g, '"') : match[2]);
}
console.log(values); // Tuloste: ["John", "Doe", "123, Main St", "New York"]
Kansainvälisten puhelinnumeroiden validointi
Kansainvälisten puhelinnumeroiden validointi on monimutkaista vaihtelevien muotojen ja pituuksien vuoksi. Vankka ratkaisu sisältää usein kirjaston käytön, mutta yksinkertaistettu regex voi tarjota perusvalidoinnin:
const phoneRegex = /^\+(?:[0-9] ?){6,14}[0-9]$/;
console.log(phoneRegex.test("+1 555 123 4567")); // Tuloste: true (USA-esimerkki)
console.log(phoneRegex.test("+44 20 7946 0500")); // Tuloste: true (UK-esimerkki)
console.log(phoneRegex.test("+81 3 3224 5000")); // Tuloste: true (Japani-esimerkki)
console.log(phoneRegex.test("123-456-7890")); // Tuloste: false
Salasanan vahvuuden validointi
Säännölliset lausekkeet ovat hyödyllisiä salasanan vahvuuskäytäntöjen valvonnassa. Alla oleva esimerkki tarkistaa vähimmäispituuden, ison kirjaimen, pienen kirjaimen ja numeron.
const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/;
console.log(passwordRegex.test("P@ssword123")); // Tuloste: true
console.log(passwordRegex.test("password")); // Tuloste: false (ei isoa kirjainta tai numeroa)
console.log(passwordRegex.test("Password")); // Tuloste: false (ei numeroa)
console.log(passwordRegex.test("Pass123")); // Tuloste: false (ei pientä kirjainta)
console.log(passwordRegex.test("P@ss1")); // Tuloste: false (alle 8 merkkiä)
Regex-optimointitekniikat
Säännölliset lausekkeet voivat olla laskennallisesti raskaita, erityisesti monimutkaisilla malleilla tai suurilla syötteillä. Tässä on joitakin tekniikoita regex-suorituskyvyn optimoimiseksi:
- Ole tarkka: Vältä liian yleisten mallien käyttöä, jotka voivat täsmätä enemmän kuin on tarkoitus.
- Käytä ankkureita: Ankkuroi regex merkkijonon alkuun tai loppuun aina kun mahdollista (
^,$). - Vältä takaisinperäytymistä (Backtracking): Minimoi takaisinperäytyminen käyttämällä possessiivisia kvanttoreita (esim.
+++:n sijaan) tai atomisia ryhmiä ((?>...)), kun se on tarkoituksenmukaista. - Käännä kerran: Jos käytät samaa regexiä useita kertoja, käännä se kerran ja käytä samaa
RegExp-oliota uudelleen. - Käytä merkkiluokkia viisaasti: Merkkiluokat (
[]) ovat yleensä nopeampia kuin vaihtoehdot (|). - Pidä se yksinkertaisena: Vältä liian monimutkaisia regex-lausekkeita, joita on vaikea ymmärtää ja ylläpitää. Joskus monimutkaisen tehtävän jakaminen useisiin yksinkertaisempiin regex-lausekkeisiin tai muiden merkkijonon käsittelytekniikoiden käyttö voi olla tehokkaampaa.
Yleiset Regex-virheet
- Metamerkkien ohittamisen unohtaminen: Erikoismerkkien, kuten
.,*,+,?,$,^,(,),[,],{,},|ja\, ohittamisen laiminlyönti, kun haluat täsmätä ne kirjaimellisesti. .(piste) -merkin ylikäyttö: Piste täsmää mihin tahansa merkkiin (paitsi rivinvaihtoon joissakin tiloissa), mikä voi johtaa odottamattomiin täsmäyksiin, jos sitä ei käytetä huolellisesti. Ole tarkempi, kun mahdollista, käyttämällä merkkiluokkia tai muita rajoittavampia malleja.- Ahneus (Greediness): Oletuksena kvanttorit, kuten
*ja+, ovat ahneita ja täsmäävät mahdollisimman paljon. Käytä laiskoja kvanttoreita (*?,+?), kun sinun on täsmättävä lyhin mahdollinen merkkijono. - Ankkurien virheellinen käyttö:
^(merkkijonon/rivin alku) ja$(merkkijonon/rivin loppu) -merkkien toiminnan väärinymmärtäminen voi johtaa virheellisiin täsmäyksiin. Muista käyttääm(multiline) -lippua, kun työskentelet monirivisten merkkijonojen kanssa ja haluat^ja$-merkkien täsmäävän kunkin rivin alkuun ja loppuun. - Reunatapauksien käsittelemättä jättäminen: Kaikkien mahdollisten syötetapausten ja reunatapauksien huomiotta jättäminen voi johtaa bugeihin. Testaa regex-lausekkeesi perusteellisesti erilaisilla syötteillä, mukaan lukien tyhjät merkkijonot, virheelliset merkit ja raja-arvot.
- Suorituskykyongelmat: Liian monimutkaisten ja tehottomien regex-lausekkeiden rakentaminen voi aiheuttaa suorituskykyongelmia, erityisesti suurilla syötteillä. Optimoi regex-lausekkeesi käyttämällä tarkempia malleja, välttämällä tarpeetonta takaisinperäytymistä ja kääntämällä toistuvasti käytettävät regex-lausekkeet.
- Merkkikoodauksen huomiotta jättäminen: Merkkikoodausten (erityisesti Unicoden) virheellinen käsittely voi johtaa odottamattomiin tuloksiin. Käytä
u-lippua, kun työskentelet Unicode-merkkien kanssa varmistaaksesi oikean täsmäytyksen.
Yhteenveto
Säännölliset lausekkeet ovat arvokas työkalu mallien täsmäytykseen ja tekstin käsittelyyn JavaScriptissä. Regex-syntaksin ja -tekniikoiden hallitseminen antaa sinun ratkaista tehokkaasti laajan valikoiman ongelmia, aina tietojen validoinnista monimutkaiseen tekstinkäsittelyyn. Ymmärtämällä tässä oppaassa käsiteltyjä konsepteja ja harjoittelemalla todellisen maailman esimerkeillä voit tulla taitavaksi säännöllisten lausekkeiden käytössä ja parantaa JavaScript-kehitystaitojasi.
Muista, että säännölliset lausekkeet voivat olla monimutkaisia, ja on usein hyödyllistä testata niitä perusteellisesti käyttämällä online-regex-testaajia, kuten regex101.com tai regexr.com. Tämä antaa sinun visualisoida täsmäykset ja korjata mahdolliset ongelmat tehokkaasti. Iloista koodaamista!