আমি ভেবেছিলাম রেজেক্স কন্ডিশনাল সম্পর্কে গতকালের নিবন্ধটি অনুসরণ করা মজাদার হবে কিছু অন্যান্য ঝরঝরে কৌশলগুলি দেখে যা আপনি রুবিতে নিয়মিত অভিব্যক্তির সাথে করতে পারেন।
রেগুলার এক্সপ্রেশনের মাধ্যমে স্ট্রিং বিভক্ত করা
আপনি সম্ভবত পাঠ্য বিভাজক ব্যবহার করে স্ট্রিং বিভক্ত করার সাথে বেশ পরিচিত:
"one,two".split(",")
# => ["one", "two"]
কিন্তু আপনি কি জানেন যে বিভাজন একটি নিয়মিত অভিব্যক্তি গ্রহণ করবে?
# use `,` and `-` as delimiters
"one,two-three".split(/,|-/)
=> ["one", "two", "three"]
# Use comma as thousands separator for US currency,
# but use a space for Euros
"1,000USD".split /(?=.*(USD))(?(1),| )/
ডিলিমিটার ক্যাপচার করা
এখানে একটি ঝরঝরে পার্টি কৌশল আছে. সাধারণত, যখন আপনি একটি স্ট্রিং বিভক্ত করেন, তখন বিভাজনকারীগুলি চলে যায়:
# The commas vanish!
"one,two".split(",")
# => ["one", "two"]
কিন্তু যদি আপনি একটি রেগুলার এক্সপ্রেশন ব্যবহার করেন এবং আপনি একটি গ্রুপের ভিতরে ডিলিমিটার রাখেন, split
ডিলিমিটারও ক্যাপচার করবে।
"one,two-three".split(/(,|-)/)
=> ["one", ",", "two", "-", "three"]
এটি হওয়ার কারণ হল split
আসলে প্রতিটি ক্যাপচার গ্রুপের সীমানায় স্ট্রিংকে বিভক্ত করে।
অপব্যবহার split
আপনি split
অপব্যবহার করতে পারেন এটি প্রায় match
এর মত আচরণ করতে . নীচের কোডে, আমি স্ট্রিংটিকে 4 টুকরাতে বিভক্ত করতে নিয়মিত এক্সপ্রেশনে চারটি গ্রুপ ব্যবহার করছি।
"1-800-555-1212".split(/(1)-(\d{3})-(\d{3})-(\d{4})/)
=> ["", "1", "800", "555", "1212"]
ফলাফলের অ্যারের প্রথম আইটেমটি একটি খালি স্ট্রিং কারণ রেগুলার এক্সপ্রেশন পুরো সোর্স স্ট্রিংয়ের সাথে মেলে।
গ্লোবাল ম্যাচিং
ডিফল্টরূপে, রেগুলার এক্সপ্রেশন শুধুমাত্র একবার একটি প্যাটার্নের সাথে মিলবে। নীচের কোডে, পাঁচটি সম্ভাব্য ম্যাচ থাকা সত্ত্বেও আমরা শুধুমাত্র একটি ম্যাচ পাই।
"12345".match /\d/
=> #<MatchData "1">
পার্লের মতো অন্যান্য ভাষায়, সমাধানটি হবে নিয়মিত অভিব্যক্তিটিকে "গ্লোবাল" হিসাবে ফ্ল্যাগ করা। রুবির সেই বিকল্পটি নেই, তবে এটিতে String#scan
আছে পদ্ধতি
scan
পদ্ধতি সমস্ত মিল ধারণকারী একটি অ্যারে প্রদান করে:
"12345".scan /\d/
=> ["1", "2", "3", "4", "5"]
এমনকি এটিতে একটি সহজ ব্লক সিনট্যাক্স রয়েছে:
"12345".scan /\d/ do |i|
puts i
end
দুর্ভাগ্যবশত, অলসভাবে একটি স্ট্রিং স্ক্যান করার কোনো উপায় আছে বলে মনে হচ্ছে না। তাই এই কৌশলটি সম্ভবত একটি 500mb ফাইল প্রক্রিয়াকরণের জন্য উপযুক্ত নয়।
গ্রুপগুলির সাথে স্ক্যান করা
এখন এই মুহুর্তে আমি আশা করি আপনি ভাবছেন যে আমাদের স্ক্যানে গ্রুপগুলি ব্যবহার করে আমরা কী ধরণের অদ্ভুত কৌশল করতে পারি।
দুর্ভাগ্যবশত, এখানে আচরণ সম্পূর্ণরূপে অনুমানযোগ্য এবং বিরক্তিকর। গোষ্ঠীগুলি একটি বহুমাত্রিক অ্যারেতে পরিণত হয়:
"hiho hiho".scan /(hi)(ho)/
=> [["hi", "ho"], ["hi", "ho"]]
একটি অদ্ভুত প্রান্ত কেস আছে. আপনি যদি গ্রুপ ব্যবহার করেন, তাহলে গ্রুপে নেই এমন কিছু ফেরত দেওয়া হবে না।
"hiho hiho".scan /(hi)ho/
=> [["hi"], ["hi"]]
শর্টহ্যান্ড
আমি বাজি ধরে বলতে পারি আপনি =~
সম্পর্কে জানেন একটি রেগুলার এক্সপ্রেশন একটি স্ট্রিং এর সাথে মেলে কিনা তা পরীক্ষা করার উপায় হিসাবে। এটি অক্ষরের সূচী প্রদান করে যেখানে ম্যাচটি শুরু হয়।
"hiho" =~ /hi/
# 0
"hiho" =~ /ho/
# 2
যদিও একটি ম্যাচের জন্য চেক করার আরেকটি দ্রুত উপায় আছে। আমি ===
এর কথা বলছি অপারেটর.
/hi/ === "hiho"
# true
যখন আমরা a === b
লিখি রুবিতে, আমরা জিজ্ঞাসা করছি "বি কি a দ্বারা সংজ্ঞায়িত সেটের অন্তর্গত"। অথবা এই ক্ষেত্রে, "'hiho' কি regex /hi/
দ্বারা মিলিত স্ট্রিংগুলির সেটের অন্তর্গত "।
===
রুবির কেস স্টেটমেন্টে অপারেটর অভ্যন্তরীণভাবে ব্যবহৃত হয়। এর মানে হল যে আপনি কেস স্টেটমেন্টেও রেগুলার এক্সপ্রেশন ব্যবহার করতে পারেন।
case "hiho"
when /hi/
puts "match"
end
ট্রিপল-ইকুয়াল অপারেটর আপনার নিজস্ব পদ্ধতিগুলিকে রেগুলার এক্সপ্রেশন বা স্ট্রিং গ্রহণ করতে দেওয়ার জন্যও কার্যকর হতে পারে।
কল্পনা করুন যে আপনি কিছু কোড কার্যকর করতে চান যখন একটি ত্রুটি ঘটে, যদি না এটি উপেক্ষা করার জন্য ক্লাসের একটি পূর্ব-কনফিগার করা তালিকায় থাকে। নীচের উদাহরণে, আমরা ===
ব্যবহার করি অপারেটর ব্যবহারকারীকে একটি স্ট্রিং বা একটি নিয়মিত অভিব্যক্তি নির্দিষ্ট করার অনুমতি দেয়।
def ignored?(error)
@ignored_patterns.any? { |x| x === error.class.name }
end
এটাই!
নিশ্চিত হওয়ার জন্য, রুবি এবং রেল জুড়ে ছড়িয়ে ছিটিয়ে থাকা এরকম কয়েক ডজন ছোট কৌশল রয়েছে। যদি আপনার বিশেষ পছন্দের একটি থাকে, আমাকে জানান!