A regexp csomag támogatást nyújt a reguláris kifejezésekhez Go-ban.
Az elfogadott reguláris kifejezések szintaxisa ugyanaz az általános szintaxis, amelyet a Perl, a Python és más nyelvek használnak.
A keresési minták és a bemeneti szövegek is UTF-8-ként értelmeződnek.
Amikor backtickeket használunk sztringek létrehozásához, a fordított perjelek () to make strings, backslashes () nem jelentenek semmit, és nem jelölik speciális karakterek, például tabulátor ) don't have any special meaning and don't mark the beginning of special characters like tabs vagy sortörés or newlines kezdetét:
"\t\n" // regular string literal with 2 characters: a tab and a newline
`\t\n`// raw string literal with 4 characters: two backslashes, a 't', and an 'n'
Emiatt a reguláris kifejezésekhez érdemes backtickeket használni, mert így nem kell escape-elni a fordított perjeleket:
"\\" // string with a single backslash
`\\` // string with 2 backslashes
RegExp típusEgy reguláris kifejezés használatához először le kell fordítanunk a sztringmintát.
A lefordítás itt azt jelenti, hogy fogjuk a reguláris kifejezés sztringmintáját, és átalakítjuk egy belső reprezentációvá, amellyel könnyebb dolgozni.
Minden mintát csak egyszer kell lefordítanunk, utána a reguláris kifejezés lefordított változatát sokszor használhatjuk.
A regexp.Regexp típus egy lefordított reguláris kifejezést reprezentál.
Egy sztringmintát a regexp.Compile függvénnyel fordíthatunk le regexp.Regexp típusúvá.
Ez a függvény nil-t és egy hibát ad vissza, ha a lefordítás nem sikerült:
re, err := regexp.Compile(`(a|b)+`)
fmt.Println(re, err) // => (a|b)+ <nil>
re, err = regexp.Compile(`a|b)+`)
fmt.Println(re, err) // => <nil> error parsing regexp: unexpected ): `a|b)+`
A MustCompile függvény kényelmes alternatívája a Compile-nak:
re = regexp.MustCompile(`[a-z]+\d*`)
Ezzel a függvénnyel nem kell a hibát kezelni.
A MustCompile-t csak akkor használd, ha biztosan tudod, hogy a minta lefordul, különben a program pánikol.
A Regexp típusnak 16 metódusa illeszt reguláris kifejezést és azonosítja az illeszkedő szöveget.
A nevükre ez a reguláris kifejezés illeszkedik:
Find(All)?(String)?(Submatch)?(Index)?
All szerepel, a metódus a teljes kifejezés egymást követő, nem átfedő illeszkedéseit keresi.String szerepel, az argumentum sztring; egyébként bájtok szelete; a visszatérési értékek ennek megfelelően módosulnak.Submatch szerepel, a visszatérési érték egy szelet, amely a kifejezés egymást követő részilleszkedéseit azonosítja.Index szerepel, az illeszkedéseket és részilleszkedéseket a bemeneti sztringen belüli bájtindexpárok azonosítják.Vannak továbbá metódusok a következőkre:
Összességében a regexp csomag több mint 40 függvényt és metódust definiál.
Az alábbiakban néhány metódus használatát mutatjuk be.
Ezeknek és más függvényeknek a részleteit lásd az API-dokumentációban.
MatchString példákA MatchString metódus megmondja, hogy egy sztring tartalmaz-e illeszkedést egy reguláris kifejezésre.
re = regexp.MustCompile(`[a-z]+\d*`)
b = re.MatchString("[a12]") // => true
b = re.MatchString("12abc34(ef)") // => true
b = re.MatchString(" abc!") // => true
b = re.MatchString("123 456") // => false
FindString példákA FindString metódus egy sztringet ad vissza, amely a reguláris kifejezés legbaloldalibb illeszkedésének szövegét tartalmazza.
re = regexp.MustCompile(`[a-z]+\d*`)
s = re.FindString("[a12]") // => "a12"
s = re.FindString("12abc34(ef)") // => "abc34"
s = re.FindString(" abc!") // => "abc"
s = re.FindString("123 456") // => ""
FindStringSubmatch példákA FindStringSubmatch metódus sztringek egy szeletét adja vissza, amely a reguláris kifejezés legbaloldalibb illeszkedésének szövegét, valamint az alkifejezéseinek illeszkedéseit tartalmazza, ha vannak ilyenek.
Ezzel azonosíthatók az elfogó csoportokra illeszkedő sztringek.
A nil visszatérési érték azt jelenti, hogy nincs illeszkedés.
re = regexp.MustCompile(`[a-z]+(\d*)`)
sl = re.FindStringSubmatch("[a12]") // => []string{"a12","12"}
sl = re.FindStringSubmatch("12abc34(ef)") // => []string{"abc34","34"}
sl = re.FindStringSubmatch(" abc!") // => []string{"abc",""}
sl = re.FindStringSubmatch("123 456") // => <nil>
ReplaceAllString példákA re.ReplaceAllString(src,repl) metódus a src egy másolatát adja vissza, amelyben a re reguláris kifejezés illeszkedéseit a repl cseresztringre cseréli.
re = regexp.MustCompile(`[a-z]+\d*`)
s = re.ReplaceAllString("[a12]", "X") // => "[X]"
s = re.ReplaceAllString("12abc34(ef)", "X") // => "12X(X)"
s = re.ReplaceAllString(" abc!", "X") // => " X!"
s = re.ReplaceAllString("123 456", "X") // => "123 456"
Split példákA re.Split(s,n) metódus a s szöveget a kifejezéssel elválasztott részsztringekre bontja, és visszaadja a kifejezés illeszkedései közötti részsztringek szeletét.
Az n szám határozza meg a visszaadandó részsztringek maximális számát.
Ha n<0, a metódus az összes részsztringet visszaadja.
re = regexp.MustCompile(`[a-z]+\d*`)
sl = re.Split("[a12]", -1) // => []string{"[","]"}
sl = re.Split("12abc34(ef)", 2) // => []string{"12","(ef)"}
sl = re.Split(" abc!", -1) // => []string{" ","!"}
sl = re.Split("123 456", -1) // => []string{"123 456"}
Ez a feladat a naplófájlok feldolgozásával foglalkozik.
Egy nemrég lezajlott biztonsági felülvizsgálat után arra kértek, hogy tisztítsd meg a szervezet archivált naplófájljait.
A függvényeknek átadott összes string garantáltan nem nullértékű, és nem tartalmaz sem vezető, sem záró szóközt.
Kell némi fogalmad arról, hogy az archívumodban hány naplósor nem felel meg a jelenlegi szabványoknak. Úgy gondolod, hogy egy egyszerű vizsgálat megmutatja, érvényes-e egy naplósor. Ahhoz, hogy egy sor érvényesnek számítson, a következő stringek egyikével kell kezdődnie:
Valósítsd meg az IsValidLine függvényt, amely false-t ad vissza, ha egy string érvénytelen, egyébként pedig true-t.
IsValidLine("[ERR] A good error here")
// => true
IsValidLine("Any old [ERR] text")
// => false
IsValidLine("[BOB] Any old text")
// => false
Egy új csapat csatlakozott a szervezethez, és azt tapasztalod, hogy a naplófájljaikban furcsa elválasztó választja el a „mezőket”. Ahelyett, hogy valami értelmeset, például kettőspontot (":") használnának, olyan stringet írnak, mint a "<--->" vagy a "<=>" (mert az szebb). Valójában bármilyen stringet, amelynek az első karaktere "<", az utolsó pedig ">", és közte a következő karakterek bármilyen kombinációja állhat: "~", "*", "=" és "-".
Valósítsd meg a SplitLogLine függvényt, amely egy sort kap, és olyan stringekből álló tömböt ad vissza, amelyek mindegyike egy mezőt tartalmaz.
SplitLogLine("section 1<*>section 2<~~~>section 3")
// => []string{"section 1", "section 2", "section 3"},
password szöveget idézőjelek közöttA csapatnak tudnia kell az idézőjelek között szereplő jelszóhivatkozásokról, hogy azokat manuálisan megvizsgálhassák.
Valósítsd meg a CountQuotedPasswords függvényt, amely jelzi, mekkora lehet a manuális vizsgálat várható mértéke.
Azonosítsd azokat a naplósorokat, amelyekben a "password" stringet idézőjelek veszik körül, és amelyben a kis- és nagybetűk bármilyen kombinációban szerepelhetnek. Számolj azzal a lehetőséggel, hogy az idézőjelek között a "password" előtt és után további tartalom is lehet. Minden sor legfeljebb két idézőjelet tartalmaz.
A rutinnak átadott sorok érvényesek is lehetnek, meg nem is, az 1. részfeladatban meghatározottak szerint. Ugyanúgy dolgozzuk fel őket, akár érvényesek, akár nem.
lines := []string{
`[INF] passWord`, // contains 'password' but not surrounded by quotation marks
`"passWord"`, // count this one
`[INF] User saw error message "Unexpected Error" on page load.`, // does not contain 'password'
`[INF] The message "Please reset your password" was ignored by the user`, // count this one
}
// => 2
Rájöttél, hogy a naplók valamelyik feldolgozási lépése szétszórta a naplókban az "end-of-line" szöveget, amelyet egy sorszám követ (közöttük szóköz nélkül).
Valósítsd meg a RemoveEndOfLineText függvényt, amely átvesz egy stringet, eltávolítja belőle az end-of-line szöveget, és egy „tiszta” stringet ad vissza.
Az end-of-line szöveget nem tartalmazó sorokat változatlanul kell visszaadni.
Csak az end-of-line stringet távolítsd el. Ne próbáld módosítani a szóközöket.
RemoveEndOfLineText("[INF] end-of-line23033 Network Failure end-of-line27")
// => "[INF] Network Failure "
Észrevetted, hogy néhány naplósor olyan mondatot tartalmaz, amely felhasználókra utal.
Ezek a mondatok mindig tartalmazzák a "User" stringet, amelyet egy vagy több szóköz, majd egy felhasználónév követ.
Úgy döntesz, hogy megcímkézed ezeket a sorokat.
Valósítsd meg a TagWithUserName függvényt, amely feldolgozza a naplósorokat:
"User " stringet, változatlanok maradnak."User " stringet, a sor elé írd a [USR] előtagot, majd a felhasználónevet.Például:
result := TagWithUserName([]string{
"[WRN] User James123 has exceeded storage space.",
"[WRN] Host down. User Michelle4 lost connection.",
"[INF] Users can login again after 23:00.",
"[DBG] We need to check that user names are at least 6 chars long.",
})
// => []string {
// "[USR] James123 [WRN] User James123 has exceeded storage space.",
// "[USR] Michelle4 [WRN] Host down. User Michelle4 lost connection.",
// "[INF] Users can login again after 23:00.",
// "[DBG] We need to check that user names are at least 6 chars long."
// }
Feltételezheted, hogy:
"User " string.Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) Go nyelvet 34 fogalom165 feladat segítségével, valódi emberi mentorálással, mindez ingyen.