রেগুলার এক্সপ্রেশন হলো স্ট্রিং প্যাটার্ন ম্যাচ করার একটি অত্যন্ত বহুমুখী উপায়, আর এর জন্য কাজে লাগানো হয় বিশেষভাবে তৈরি একটি ডোমেইন স্পেসিফিক ভাষা (DSL)।
অন্যান্য অনেক প্রোগ্রামিং ভাষার মতো Julia-ও নিজস্ব Regex লাইব্রেরি বানানোর চেষ্টা করে না। বরং এটি জনপ্রিয় PCRE2 লাইব্রেরিকে ঘিরে কাজ করে, ফলে যে Regex সিনট্যাক্স পাওয়া যায় তা (উদাহরণস্বরূপ) Gleam-এর সঙ্গে হুবহু এক, আর Javascript-এর সঙ্গে খুবই কাছাকাছি।
এই Julia সিলেবাসটি ধরে নেয় যে আপনি মৌলিক Regex সিনট্যাক্সের সঙ্গে আগেই পরিচিত। আমরা শুধু Julia-নির্দিষ্ট বৈশিষ্ট্যগুলো নিয়েই আলোচনা করব।
আপনার রেগুলার এক্সপ্রেশনের জ্ঞান ঝালিয়ে নেওয়ার জন্য কিছু রিসোর্স নিচে দেওয়া হলো।
রেগুলার এক্সপ্রেশনের সঙ্গে Julia-র ইন্টারফেসের বর্ণনা আছে ম্যানুয়ালে।
Julia-তে একটি রেগুলার এক্সপ্রেশন আসলে একটি স্ট্রিং, যার খোলা "-এর আগে r বসানো হয়। এর সব মৌলিক সুবিধাই স্ট্যান্ডার্ড লাইব্রেরির অংশ।
আসলে, Strings কনসেপ্টে আগেই আলোচনা করা অনেক ফাংশনই স্বাভাবিকভাবেই Regex অনুসন্ধানের জন্য তৈরি, যেমন 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
ক্লোজিং কোটের পরে মডিফায়ার ক্যারেক্টার বসানো যায়, যেমন কেস-ইনসেনসিটিভ ম্যাচের জন্য i।
julia> occursin(r"test", "Testing")
false
julia> occursin(r"test"i, "Testing")
true
সাধারণত আমরা জানতে চাই কী ম্যাচ করেছে। এটি করার জন্য regex-এর ভেতরে বন্ধনীর মধ্যে ক্যাপচার গ্রুপ যোগ করা হয়, তারপর match() ফাংশনটি ব্যবহার করা হয়।
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
অবশ্যই, ম্যাচ ব্যর্থও হতে পারে। তখন RegexMatch-এর বদলে ফলাফল হিসেবে বিশেষ মান Nothing আসবে, তাই এটি পরীক্ষা করার জন্য প্রস্তুত থাকুন।
# failed match
m = match(r"(not here)", "dissolve 25g sugar in 200ml water")
julia> typeof(m)
Nothing
julia> isnothing(m)
true
match ডিফল্টভাবে স্ট্রিংয়ের শুরু থেকে খোঁজা শুরু করলেও, আমরা একটি অফসেট n উল্লেখ করে প্রথম nটি ক্যারেক্টার এড়িয়ে যেতে পারি।
# 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")
Julia-তে match() টার্গেট স্ট্রিংয়ের ভেতরে শুধু প্রথম ম্যাচটি খুঁজে পায়: অন্য কিছু ভাষার মতো এখানে কোনো গ্লোবাল মডিফায়ার নেই।
এর বদলে আমাদের আছে eachmatch(), যা ম্যাচগুলোর একটি ইটারেটর রিটার্ন করে। এটি অলস মূল্যায়নে চলে, তাই আপনার পছন্দের ফরম্যাটে এটি রূপান্তর করার দরকার হতে পারে।
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"
ডিফল্টভাবে ওভারল্যাপিং ম্যাচ অনুমোদিত নয়। এটি বদলাতে overlap = true কিওয়ার্ড আর্গুমেন্ট হিসেবে যোগ করুন।
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")
Regex ব্যবহারের একটি কমন কারণ হলো ম্যাচটি অন্য একটি স্ট্রিং দিয়ে বদলে দেওয়া।
replace() ফাংশনটি Strings কনসেপ্টে আলোচনা করা হয়েছে, যেখানে খোঁজার জন্য স্ট্রিং লিটারেল ব্যবহার করা হয়। একই ফাংশন Regex ম্যাচিংয়ের পূর্ণ শক্তি কাজে লাগাতে পারে।
julia> replace("some string", r"[aeiou]" => "*")
"s*m* str*ng"
julia> replace("first second", r"(\w+) (?<agroup>\w+)" => s"\g<agroup> \1")
"second first"
উপরের দ্বিতীয় উদাহরণটি দেখায় যে একটি s" " স্ট্রিংয়ের ভেতরে রিপ্লেসমেন্টে নাম্বারযুক্ত ও নামযুক্ত, দুধরনের ক্যাপচার গ্রুপই কীভাবে ব্যবহার করা যায়।
আরও বিস্তারিত জানতে ম্যানুয়াল দেখুন: এটি এমন একটি বিষয় যা বেশিরভাগ প্রোগ্রামারকে বারবার ডকুমেন্টেশনে ফিরে যেতে বাধ্য করে!