A reguláris kifejezések rendkívül sokoldalú módot kínálnak a stringek mintaillesztésére, egy erre a célra tervezett tartományspecifikus nyelv (DSL) segítségével.
Ahogy számos más programozási nyelv, a Julia sem próbál saját Regex-könyvtárat megvalósítani. Ehelyett a népszerű PCRE2 könyvtárat csomagolja be, így a Regex szintaxisa azonos például a Gleamével, és nagyon hasonló a JavaScriptéhez.
Ez a Julia-tanterv feltételezi, hogy már ismered a Regex alapvető szintaxisát. Kizárólag a Julia-specifikus funkciókra összpontosítunk.
Az alábbiakban néhány forrást találsz, amivel felfrissítheted a reguláris kifejezésekkel kapcsolatos tudásodat.
A reguláris kifejezésekhez használható Julia-interfészt a kézikönyv írja le.
Egy reguláris kifejezés a Juliában egyszerűen egy string, amelyet a nyitó " előtt egy r előz meg.
Az alapvető funkciók mind a szabványos könyvtár részei.
Valójában a Strings fogalomban már tárgyalt függvények közül sok eleve Regex-keresésre készült, például az occursin().
julia> re = r"test$"
r"test$"
julia> typeof(re)
Regex
# Does a string end with "test"?
julia> occursin(re, "this is a test")
true
julia> occursin(re, "these are tests")
false
A záró idézőjel után módosító karakterek állhatnak, például i a kis- és nagybetűkre nem érzékeny illesztéshez.
julia> occursin(r"test", "Testing")
false
julia> occursin(r"test"i, "Testing")
true
Gyakran szeretnénk tudni, hogy mi illeszkedett. Ezt úgy érhetjük el, hogy elkapó csoportokat teszünk zárójelbe a regexen belül, majd a match() függvényt használjuk.
julia> m = match(r"(\d+g) .* (\d+ml)", "dissolve 25g sugar in 200ml water")
RegexMatch("25g sugar in 200ml", 1="25g", 2="200ml")
julia> m.captures
2-element Vector{Union{Nothing, SubString{String}}}:
"25g"
"200ml"
# how many matches?
julia> length(m.captures)
2
# what matched?
julia> m[1], m[2]
("25g", "200ml")
# Starting positions of the matches (character index)
julia> m.offsets
2-element Vector{Int64}:
10
23
Persze az illesztés sikertelen is lehet.
Ilyenkor az eredmény a különleges Nothing érték lesz a RegexMatch helyett, ezért készülj fel arra, hogy ezt is ellenőrizd.
# failed match
m = match(r"(not here)", "dissolve 25g sugar in 200ml water")
julia> typeof(m)
Nothing
julia> isnothing(m)
true
Bár a match alapértelmezés szerint a string elejétől indul, megadhatunk egy n eltolást is, hogy figyelmen kívül hagyjuk az első n karaktert.
# capture first match
julia> m = match(r"(\wat)", "cat, sat, mat")
RegexMatch("cat", 1="cat")
# ignore first 5 characters, then match
julia> m = match(r"(\wat)", "cat, sat, mat", 5)
RegexMatch("sat", 1="sat")
A Juliában a match() csak az első illeszkedést találja meg a célstringben: nincs globális módosító, mint néhány más nyelvben.
Ehelyett itt van az eachmatch(), amely az illeszkedések iterátorát adja vissza.
Ez lustán kiértékelt, ezért lehet, hogy a kívánt formátumba kell alakítanod.
julia> matches = eachmatch(r"(\wat)", "cat, sat, mat")
Base.RegexMatchIterator{String}(r"(\wat)", "cat, sat, mat", false)
# convert to vector
julia> collect(matches)
3-element Vector{RegexMatch}:
RegexMatch("cat", 1="cat")
RegexMatch("sat", 1="sat")
RegexMatch("mat", 1="mat")
# convert with comprehension
julia> [m.match for m in matches]
3-element Vector{SubString{String}}:
"cat"
"sat"
"mat"
# broadcast an anonymous function
julia> (m -> m.match).(matches)
3-element Vector{SubString{String}}:
"cat"
"sat"
"mat"
Az átfedő illeszkedések alapértelmezés szerint nem megengedettek.
Ezt felülírhatod, ha kulcsszóargumentumként megadod az overlap = true értéket.
julia> eachmatch(r"aba", "abababa") |> collect # matches at positions 1, 5
2-element Vector{RegexMatch}:
RegexMatch("aba")
RegexMatch("aba")
julia> eachmatch(r"aba", "abababa"; overlap = true) |> collect # also matches at position 3
3-element Vector{RegexMatch}:
RegexMatch("aba")
RegexMatch("aba")
RegexMatch("aba")
A Regex használatának egyik gyakori oka, hogy az illeszkedést egy másik stringre cseréljük.
A replace() függvényt a Strings fogalomban már tárgyaltuk, ahol string literálokkal kerestünk.
Ugyanez a függvény ki tudja használni a Regex-illesztés minden erejét.
julia> replace("some string", r"[aeiou]" => "*")
"s*m* str*ng"
julia> replace("first second", r"(\w+) (?<agroup>\w+)" => s"\g<agroup> \1")
"second first"
A fenti második példa megmutatja, hogyan használhatók a sorszámozott és a nevesített elkapó csoportok is a cserében, egy s" " stringen belül.
További részletekért nézd meg a kézikönyvet: ez egy olyan téma, amely újra és újra visszatereli a legtöbb programozót a dokumentációhoz!