রুবি রেজিপ্সপ গ্রুপের মিল, 1 লাইনে ভেরিয়েবল বরাদ্দ করুন


125

আমি বর্তমানে একাধিক ভেরিয়েবলের মধ্যে একটি স্ট্রিং পুনরুদ্ধার করার চেষ্টা করছি। উদাহরণ স্ট্রিং:

ryan_string = "RyanOnRails: This is a test"

আমি এটি 3 টি গ্রুপ সহ এই রেজিএক্সএক্সের সাথে মিলেছি:

ryan_group = ryan_string.scan(/(^.*)(:)(.*)/i)

এখন প্রতিটি গ্রুপ অ্যাক্সেস করতে আমাকে এই জাতীয় কিছু করতে হবে:

ryan_group[0][0] (first group) RyanOnRails
ryan_group[0][1] (second group) :
ryan_group[0][2] (third group) This is a test

এটি বেশ হাস্যকর বলে মনে হচ্ছে এবং মনে হচ্ছে আমি কোনও ভুল করছি। আমি এই জাতীয় কিছু করতে সক্ষম হবে আশা করি:

g1, g2, g3 = ryan_string.scan(/(^.*)(:)(.*)/i)

এটা কি সম্ভব? বা আমি কীভাবে এটি করছি তার চেয়ে ভাল উপায় আছে?

উত্তর:


199

আপনি scanএটির জন্য চান না , কারণ এটি অল্প বুদ্ধিমান। আপনি ব্যবহার করতে পারেন String#matchযা কোন MatchDataবস্তু ফেরত দেবে , তারপরে আপনি #capturesক্যাপচারের অ্যারে ফিরিয়ে আনতে কল করতে পারেন। এটার মতো কিছু:

#!/usr/bin/env ruby

string = "RyanOnRails: This is a test"
one, two, three = string.match(/(^.*)(:)(.*)/i).captures

p one   #=> "RyanOnRails"
p two   #=> ":"
p three #=> " This is a test"

সচেতন হোন যে কোনও মিল না পাওয়া গেলে String#matchশূন্য হয়ে যাবে, সুতরাং এর মতো আরও কিছু ভাল কাজ করতে পারে:

if match = string.match(/(^.*)(:)(.*)/i)
  one, two, three = match.captures
end

যদিও scanএই জন্য সামান্য জ্ঞান না। এটি এখনও কাজটি করে না, আপনাকে প্রথমে ফিরে আসা অ্যারে সমতল করতে হবে।one, two, three = string.scan(/(^.*)(:)(.*)/i).flatten


6
সাবধান হোন যদি কোনও মিল খুঁজে পাওয়া যায় না, তবে ম্যাচটি শূন্য হয়ে যায় এবং আপনি একটি নীলআরবার পাবেন। আপনি যদি one, two, three = string.match(/(^.*)(:)(.*)/i).capturesone, two, three = string.match(/(^.*)(:)(.*)/i).try(:captures)
কারাগারে থাকেন তবে

5
@ আন্দ্রেয়া স্যালিসেটি আমি আমার পোস্টটি সম্পাদনা করেছি, আমি এতে রেল-নির্দিষ্ট কোড যুক্ত করছি না তাই আমি ফিরে আসা শূন্য বস্তুটি পরিচালনার জন্য একটি সংস্করণ দিয়ে এটি পরিবর্তন করেছি
লি জারভিস

3
আপনি নতুন &.অপারেটরটিকে এটিকে কোনও লাইনে ফিরিয়ে আনতে এবং এমনকি যখন কেবলমাত্র একটি ক্যাপচার গ্রুপ রয়েছে তখনও এটি দুবার ব্যবহার করতে পারেন। উদা ..,string.match(regex)&.captures&.first
গেরি শ

46

পরিবর্তে আপনি ম্যাচ বা = use ব্যবহার করতে পারেন যা আপনাকে একক মিল দেয় এবং আপনি ম্যাচের ডেটা একইভাবে অ্যাক্সেস করতে পারেন বা বিশেষ ম্যাচ ভেরিয়েবলগুলি $ 1, $ 2, $ 3 ব্যবহার করতে পারেন

কিছুটা এইরকম:

if ryan_string =~ /(^.*)(:)(.*)/i
   first = $1
   third = $3
end

5
@ গ্যাস্টন এটি প্রকৃতপক্ষে পার্ল থেকে উদ্ভূত মূল রিজেক্সপ সিনট্যাক্স :)
ওহালেক

28

আপনি আপনার বন্দী ম্যাচের নাম রাখতে পারেন

string = "RyanOnRails: This is a test"
/(?<one>^.*)(?<two>:)(?<three>.*)/i =~ string
puts one, two, three

আপনি স্ট্রিং এবং রেজেক্সের ক্রমটি বিপরীত করলে এটি কাজ করে না।


6

আপনাকে এটি সিদ্ধান্ত নিতে হবে যে এটি একটি ভাল ধারণা, তবে রুবি রেজিএক্সপ্যাক (স্বয়ংক্রিয়ভাবে) আপনার জন্য স্থানীয় ভেরিয়েবলগুলি সংজ্ঞায়িত করতে পারে!

এই বৈশিষ্ট্যটি দুর্দান্ত বা পুরোপুরি উন্মাদ কিনা তা আমি এখনও নিশ্চিত নই, তবে আপনার রেজেক্স স্থানীয় ভেরিয়েবলগুলি সংজ্ঞায়িত করতে পারে।

ryan_string = "RyanOnRails: This is a test"
/^(?<webframework>.*)(?<colon>:)(?<rest>)/ =~ ryan_string
# This defined three variables for you. Crazy, but true.
webframework # => "RyanOnRails"
puts "W: #{webframework} , C: #{colon}, R: #{rest}"

( Http://ruby-doc.org/core-2.1.1/Regexp.html দেখুন , "স্থানীয় পরিবর্তনশীল" অনুসন্ধান করুন)।

দ্রষ্টব্য: একটি মন্তব্যে নির্দেশিত হিসাবে, আমি দেখতে পাচ্ছি @ টুনসেন্ড ( https://stackoverflow.com/a/21412455 ) দ্বারা এই প্রশ্নের একটি অনুরূপ এবং আগের উত্তর রয়েছে । আমি মনে করি না যে আমি "চুরি" করছি, তবে আপনি যদি প্রশংসার সাথে ন্যায্য হতে চান এবং প্রথম উত্তরটি সম্মান করতে চান তবে নির্দ্বিধায় :) আমি আশা করি কোনও প্রাণীর ক্ষতি হবে না।


এই উত্তরটি স্ট্যাকওভারফ্লো.com /a/ 21412455 / 525478 এর সাথে অদ্ভুতরকম দেখাচ্ছে , যা এক বছরেরও বেশি পুরানো ...
ব্র্যাড ওয়ার্থ

@ ব্র্যাডওয়ার্থ আমার ধারণা আমি কেবল এটি দেখিনি। তবে আমি আপনার উদ্বেগগুলি অন্তর্ভুক্ত করতে আমার উত্তর আপডেট করেছি।
ফেলিক্স

5

scan() আপনার স্ট্রিংয়ে রেজেক্সের সমস্ত অ-ওভারল্যাপিং ম্যাচগুলি খুঁজে পাবেন, সুতরাং আপনার গ্রুপগুলির একটি অ্যারে ফিরে আসার পরিবর্তে আপনি যেমন প্রত্যাশা করছেন বলে মনে হচ্ছে, এটি অ্যারের অ্যারে ফিরিয়ে দিচ্ছে।

আপনি সম্ভবত ব্যবহার করে আরও ভাল match(), এবং তারপরে ক্যাপচারের অ্যারে পেয়ে যাচ্ছেন MatchData#captures:

g1, g2, g3 = ryan_string.match(/(^.*)(:)(.*)/i).captures

তবে আপনি scan()যদি এটি করতে চান তবে এটি দিয়েও করতে পারেন:

g1, g2, g3 = ryan_string.scan(/(^.*)(:)(.*)/i)[0]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.