تحتوي السلاسل النصية في لغة روبي على العديد من التوابع ضمنها والتي تسهل العديد من العمليات الشائعة على السلاسل النصية سنتعرف عليها في هذا المقال، والتي تفيد مثلًا في تحديد طول السلسلة النصية أو تقسيمها واستخراج أجزاء منها، أو إضافة وإزالة المسافات البيضاء whitespace والأحرف الأخرى منها، أو تغيير حالة الأحرف فيها، أو البحث عن نص معين فيها واستبداله بآخر، لينتج عن استخدام تلك التوابع مزايا قوية يمكن الاستفادة منها لحل العديد من المشاكل.
تحديد طول سلسلة نصية
تحتوي السلاسل النصية على التابع length
والذي يُعيد عدد الأحرف في السلسلة النصية، فمثلًا يمكن الاستفادة من ذلك التابع لتحديد الحد الأدنى أو الأقصى لطول كلمة المرور في نظام ما والعديد من الاستخدامات، والمثال التالي يوضح طول سلسلة نصية مُخزنة ضمن متغير ويطبع النتيجة:
open_source = "Sammy contributes to open source." print open_source.length
ليكون الخرج على النحو التالي:
33
يجب التأكيد على أن كل المحارف ضمن السلسلة النصية بما في ذلك الحروف والأرقام والمسافات والرموز مأخوذة بالحسبان ضمن طول السلسلة النصية، ولمعرفة ما إذا كانت السلسلة النصية فارغة يمكن مقارنة طولها والتأكد بأنه يساوي الصفر 0، أو يمكن استخدام التابع المخصص لذلك وهو ?empty
على النحو التالي:
name = "" name.empty? # true name = "Sammy" name.empty? # false name = " " name.empty? # false
سنتعرف في الفقرة التالية على طريقة الوصول إلى المحارف ضمن السلسلة النصية.
الوصول إلى المحارف ضمن السلسلة النصية
توفر لغة روبي التابع slice
، الذي يفيد في استخراج جزء من السلسلة النصية. يُشار لكل محرف ضمن السلسلة النصية برقم الفهرس لها وهو رقم يبدأ ترتيبه من الصفر 0، تمامًا كما هو الحال بالنسبة للمصفوفات arrays في روبي، فمثلًا رقم الفهرس للمحارف في السلسلة النصية Sammy
هو:
4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|
y | m | m | a | S |
يسمح التابع slice
بالوصول إلى محرف واحد أو مجال من المحارف، فعند تمرير رقم صحيح واحد غليه سيُعيد المحرف الموجود في رقم الفهرس المحدد، وعند تمرير رقمين صحيحين مفصولين بفاصلة سيُعيد هذا التابع جميع المحارف بدءًا من رقم الفهرس الأول وحتى رقم الفهرس الثاني، ويمكن تمرير نطاق من الفهارس مثلًا من واحد إلى أربعة 4..1
لاستخراج الحروف الموجودة ضمن هذا النطاق:
"Sammy".slice(0) # "s" "Sammy".slice(1,2) # "am" "Sammy".slice(1..4) # "ammy"
ويمكن استخدام الصيغة []
والتي هي مرادف للتابع slice
ليصبح شكل التعامل مع السلاسل النصية مشابه للمصفوفات:
"Sammy"[0] # "s" "Sammy"[1,2] # "am" "Sammy"[1..4] # "ammy"
يمكن الوصول إلى المحارف في نهاية السلسلة النصية باستخدام رقم فهرس سالب، فمثلًا الفهرس 1-
يعيد المحرف الأخير من السلسلة النصية، والفهرس 2-
يعيد المحرف ما قبل الأخير وهكذا، ويمكن تحويل سلسلة نصية إلى مصفوفة تحتوي على المحارف المكونة لها باستخدام التابع chars
على النحو التالي:
"sammy".chars # ["S", "a", "m", "m", "y"]
يمكن استخدام هذه الطريقة للتعديل على محارف السلسلة النصية، وسنتعرف في الفقرة التالية على طريقة تغيير حالة الأحرف ضمن السلسلة النصية.
تعديل حالة الأحرف
يمكن استخدام التابع upcase
لتحويل جميع الحروف الأجنبية في السلسلة النصية إلى أحرف كبيرة، والتابع downcase
لتحويل جميع الحروف الأجنبية في السلسلة النصية إلى أحرف صغيرة، وتبقى الحروف بغير اللغة الإنجليزية كما هي دون تغيير. سنعدّل في المثال التالي السلسلة النصية "Sammy Shark" إلى حروف كبيرة:
name = "Sammy Shark" print name.upcase SAMMY SHARK
ليكون الخرج على النحو التالي:
SAMMY SHARK
ولنختبر تحويلها إلى أحرف صغيرة:
print name.downcase
سيكون الخرج هنا:
sammy shark
يسهّل استخدام التابعين upcase
و downcase
لمقارنة السلاسل النصية مع بعضها عن طريق توحيد حالة الأحرف قبل المقارنة، فمثلًا عند إدخال اسم مستخدم في برنامج ما من قِبل المستخدم بأحرف كبيرة، فيمكن تحويل القيمة المُدخلة إلى حروف صغيرة ثم مقارنتها القيم الموجودة ضمن النظام بأحرف صغيرة. توفر روبي أيضًا التابع capitalize
، الذي يعيد نسخةً جديدةً من السلسلة النصية مع تحويل الحرف الأول منها إلى حرف كبير:
"sammy".capitalize # "Sammy"
وتوفر روبي أيضًا التابع swapcase
والذي يعيد نسخةً جديدةً من السلسلة النصية مع تبديل حالة كل الأحرف فيها:
text = "Sammy" print text.swapcase
وسيكون الخرح في هذه الحالة:
sAMMY
تعيد التوابع downcase
و upcase
و capitalize
و swapcase
نسخةً جديدةً من السلسلة النصية وتترك السلسلة الأصلية دون تغيير، ويتوضح ذلك عند التعديل على قيمة سلسلة نصية مُخزنة ضمن متغير ما، فتبقى القيمة ضمن المتغير كما هي دومًا دون تغيير في حال لم نسنِد القيمة الجديدة مجددًا إلى المتغير:
text = "sammy" text.capitalize print "Hello, #{text}!"
ويكون الخرج على النحو التالي:
Hello, sammy!
على الرغم من استخدامنا للتابع capitalize
على المتغير text
في المثال السابق، وبما أننا لم نخزن القيمة المُعادة من capitalize
مجددًا داخل المتغير text
، فقيمة المتغير text
لم تتغير، ولتغييرها يمكن إعادة كتابة الشيفرة السابقة بالشكل التالي لحل هذه المشكلة:
text = "sammy" text = text.capitalize print "Hello, #{text}!"
ويكون الخرح:
Hello, Sammy!
يمكن استخدام التوابع !downcase
و !upcase
و !capitalize
و !swapcase
(لاحظ انتهاء أسمائها بالمحرف !
) للتعديل على قيمة السلسلة النصية الأصلية بدلًا من إنشاء سلسلة جديدة:
text = "sammy" text = text.capitalize! print "Hello, #{text}!"
ويجب الانتباه عند التعديل على قيمة السلسلة النصية الأصلية؛ فقد تعدّل قيمة سلسلة نصية في مكان ما ضمن البرنامج دون الانتباه إليه ما يؤدي لمشاكل، وسنتعرف في الفقرة التالية على طريقة إضافة وإزالة المسافات البيضاء من السلاسل النصية.
إضافة وإزالة المسافات البيضاء الفارغة
يمكن إضافة المسافات قبل أو بعد أو على كلا طرفي السلسلة النصية لتعديل تنسيقها قبل طباعتها مثلًا، وقد نحتاج أحيانًا لإزالة الأحرف غير الضرورية من بداية أو نهاية السلاسل النصية مثل المسافات الزائدة أو المحارف الخاصة. نبدأ بالتعرف على التابع center
، الذي نمرر له طول السلسلة النصية الناتجة التي نريدها وسيضمن أنها بالطول المحدد، وذلك بإضافة مسافات بيضاء حول السلسلة نصية التي يُعالجها على النحو التالي:
"Sammy",center(21) # " Sammy "
ويمكننا استبدال المسافات البيضاء بنص معين نريد إضافته بتمريره لذلك التابع مثل وسيط ثانِ على النحو التالي:
" [Sammy] ".center(21, "<>") # "<><><> [Sammy] <><><>"
يضيف التابعان ljust
و rjust
مسافات بيضاء أو أحرف معينة إلى الجهة اليسرى أو اليمنى من السلسلة النصية ويعملان بالطريقة نفسها التي يعمل بها التابع center
:
"Sammy".ljust(20) # "Sammy " "Sammy".rjust(20) # " Sammy" "Sammy".rjust(20, "!") # "!!!!!!!!!!!!!!!Sammy"
يمكن استخدام التابع rstrip
لإزالة المسافات الزائدة في بداية السلسلة النصية، كما يمكن استخدام التابع lstrip
لإزالة المسافات الزائدة في نهاية السلسلة النصية، أما التابع strip
فيزيل المسافات الزائدة في كلا الجهتين (البداية والنهاية) من السلسلة النصية:
" Sammy".rstrip # "Sammy" "Sammy ".lstrip # "Sammy" " Sammy ".strip # "Sammy"
يمكن أيضًا استخدام التوابع !center
و !ljust
و !rjust
و !lstrip
و !rstrip
و !strip
لتعديل قيمة السلسلة النصية الأصلية، وفي بعض الأحيان قد نحتاج لإزالة الأحرف من نهاية السلسلة النصية لذلك يمكن استخدام التابع chop
لإزالة المحرف الأخير من السلسلة النصية:
"Sammy".chop # "Samm"
قد نستفيد من ذلك لإزالة محرف السطر الجديد n\
مثلًا من نهاية سلسلة نصية ما:
"This string has a newline\n".chop
يترك التابع chop
السلسلة النصية الأصلية دون تعديل ويعيد قيمة سلسلة نصية جديدة بدون المحرف الأخير، بينما يعدل التابع !chop
السلسلة النصية الأصلية بدلًا من إنشاء سلسلة جديدة، ويمكن استخدام التابع chomp
لإزالة عدة محارف من نهاية السلسلة النصية على النحو التالي:
"Sammy".chomp("my") # "Sam"
وفي حال لم نحدد السلسلة النصية التي نريد إزالتها من النهاية فسيزيل التابع chomp
محرف السطر الجديد n\
فقط:
"This string has a newline\n".chomp # "This string has a newline
وفي حال لم تحتوي السلسلة النصية على محرف السطر الجديد n\
فسيعيد التابع chomp
السلسلة النصية الأصلية كما هي دون تعديل:
"Sammy".chomp # "Sammy"
استخدام التابع chomp
أسهل لإزالة محارف السطر الجديد n\
من نهاية السلسلة النصية من التابع chop
والذي يزيل دائمًا الحرف الأخير مهما كان نوعه، كما توفر لغة روبي التابع !chomp
، الذي يعدل قيمة السلسلة النصية الأصلية ويعيد السلسلة النصية المعدلة إذا أزال محارف من نهاية السلسلة، ولكن وعلى عكس التابع chomp
فسيعيد التابع !chomp
القيمة nil
إذا لم يُعدل على السلسلة النصية:
string = "Hello\n" string.chomp! # "Hello" string = "Hello" string.chomp! # nil
سنتعرف في الفقرة التالية على طريقة البحث ضمن السلاسل النصية.
البحث عن المحارف والنصوص
نحتاج أحيانًا لتحديد ما إذا كانت السلسلة النصية تحتوي على نص معين أم لا، لهذا الغرض توفر روبي التابع ?include
، الذي يتحقق مما إذا كانت السلسلة النصية تحتوي على سلسلة نصية أخرى، ويعيد القيمة المنطقية true
إذا كانت السلسلة النصية تحتوي على السلسلة النصية الأخرى، أو القيمة false
في حال لم تحتويها:
"Sammy".include?("a") # true "Sammy".include?("b") # false
يعيد التابع index
رقم الفهرس لمكان محرف أو سلسلة نصية ما، أو يعيد القيمة nil
في حال عدم العثور على المحرف أو السلسلة النصية الجزئية ضمنها:
"Sammy".index("a") # 1 "Sammy".index("mm") # 2 "Sammy".index("Fish") # nil
يبحث التابع index
عن أول تواجد للمحرف أو السلسلة النصية المطلوبة فقط ويعيد رقم الفهرس له. لنوضح ذلك في المثال التالي على سلسلة نصية طويلة:
text = "Sammy has a balloon" text.index("a") # 1
تحتوي السلسلة النصية "Sammy has a balloon" على أربعة حروف "a"، ولكن التابع index
يعيد فقط موقع أول ظهور لذلك الحرف، ويجب أخذ ذلك بالحسبان عند البحث ضمن السلاسل النصية، ولتحديد كل ظهور للحرف "a" ضمن الجملة السابقة يمكن تحويل السلسلة النصية إلى مصفوفة من الأحرف المكونة لها ثم الاستعانة بتوابع المصفوفة للبحث بين تلك الحروف عن كل مكان لذلك الحرف وتحديد رقم الفهرس له مثلًا على النحو التالي:
text = "Sammy has a balloon" indices = text.chars .each_with_index .select{|char, index| char == "a" } .map{|pair| pair.last} print indices [1, 7, 10, 13]
ليكون الخرج على النحو التالي:
[1, 7, 10, 13]
يعيد التابع each_with_index
مصفوفة ثنائية الأبعاد يحتوي كل عنصر منها على الحرف ومكانه ضمن السلسلة النصية، ونختار ضمن التابع select
العناصر التي تحتوي على الحرفa
، ثم نحول تلك العناصر باستخدام التابع map
إلى مصفوفة تحتوي على رقم الفهرس لكل تواجد للحرف a
، ويمكن التحقق مما إذا كانت السلسلة النصية تبدأ بحرف أو سلسلة نصية معينة باستخدام التابع ?start_with
كما يلي:
text = "Sammy has a balloon" text.start_with?("s") # true text.start_with?("Sammy has" # true
يقبل التابع ?start_with
سلسلةً نصيةً واحدةً أو أكثر مثل وسطاء له، ويعيد true
إذا تطابق أي من تلك السلاسل النصية مع بداية السلسلة الأصلية:
text = "Sammy has a balloon" text.start_with?("Sammy the Shark", "Sammy") # true
لم يُعثر في هذا المثال على السلسلة النصية "Sammy the Shark"، ولكن عُثر على السلسلة النصية "Sammy"، لذا أرجع التابع القيمة true
، وبالمقابل يمكن استخدام التابع ?end_with
للتحقق مما إذا كانت السلسلة النصية تنتهي بسلسلة نصية معينة، إذ يعمل هذا التابع بنفس طريقة عمل التابع ?start_with
:
text = "Sammy has a balloon" text.end_with?("balloon") # true text.end_with?("boomerang") # false text.end_with?("boomerang", "balloon") # true
بعد أن تعرفنا على طرق البحث ضمن النصوص، سنتعرف في الفقرة التالية على طريقة استبدال أجزاء معينة من السلسلة النصية.
استبدال أجزاء من النص في السلاسل النصية
يمكن البحث عن سلسلة نصية واستبدالها بأخرى باستخدام خاصية البحث والاستبدال المتوفرة عادةً في محررات النصوص التي نستخدمها، ويمكن تنفيذ هذه الميزة في لغة روبي باستخدام التوابع sub
و gsub
، إذ يبدل التابع sub
جزءًا من النص بجزء آخر. سنغيّر في المثال التالي الجزء "has"
إلى "had"
في الجملة التالية:
balloon = "Sammy has a balloon" print balloon.sub("has","had")
ليعيد التابع قيمة النص بعد التبديل:
Sammy had a balloon.
يستبدل التابع sub
أول ورود للنص المطابق بالنص الجديد فقط. لتوضيح ذلك سنستخدم الجملة التالية المعدّلة التي تحتوي على ورودين للكلمة "has"
:
balloon = "Sammy has a balloon. The balloon has a ribbon" print balloon.sub("has","had")
وسيكون الخرج على النحو التالي:
Sammy had a balloon. The balloon has a ribbon
نلاحظ تبديل أول ظهور فقط، ولتبديل جميع الأماكن التي ترد فيها السلسلة النصية يمكن استخدام التابع gsub
الذي يبدل على مستوى النص بأكمله:
balloon = "Sammy has a balloon. The balloon has a ribbon" print balloon.gsub("has","had") Sammy had a balloon. The balloon had a ribbon
ويكون الخرج:
Sammy had a balloon. The balloon had a ribbon
تعيد التوابع sub
و gsub
سلسلةً نصيةً جديدةً دون تعديل السلسلة الأصلية، ويمكن توضيح ذلك بتغيير الكلمة "balloon" إلى "boomerang" في السلسلة النصية التالية:
text = "Sammy has a balloon" text.gsub("ballooon", "boomerang") print text Sammy has a balloon
التي تعطي الخرج التالي:
Sammy has a balloon
نلاحظ بقاء النص كما هو على الرغم من إمكانية الاستبدال، وذلك لأننا لم نخزن نتيجة التابع gsub
في المتغير مجددًا، وللحصول على النتيجة التي نريدها يمكننا تعديل الشيفرة كما يلي:
text = "Sammy has a balloon" text = text.sub("ballooon", "boomerang") print text
أو يمكن استخدام التابع !sub
بدلًا من التابع sub
والذي يعدل على السلسلة الأصلية بدلًا من إعادة سلسلة جديدة. سنستخدم في المثال التالي التابع !sub
لتغيير الجملة "red balloon" إلى "blue boomerang":
text = "Sammy has a red balloon" text.sub!("red", "blue") text.sub!("balloon", "boomerang") print text
ليكون الخرج على النحو التالي:
Sammy has a balloon
يمكن استخدام التابع !gsub
لاستبدال كل ورود للنص المحدد والتعديل على قيمة السلسلة النصية الأصلية، ويمكن تمرير التعابير النمطية Regular Expressions -أو اختصارًا regex- للتوابع sub
و gsub
للبحث عن نمط معين، ففي المثال التالي سنبدل جميع الحروف الصوتية ضمن النص بالرمز @
:
"Sammy has a red balloon".gsub(/[aeiou]/, "@")
وسيكون الخرج على النحو التالي:
"S@mmy h@s @ r@d b@ll@@n"
ويمكن تمرير جدول Hash بدلًا من سلسلة نصية ثابتة لتحديد كيفية استبدال كل جزء من النص الوارد بصورةٍ مختلفة، ففي المثال التالي سنبدّل جميع حروف "a" إلى المحرف "@" وجميع الحروف "o" إلى الرقم صفر:
"Sammy has a red balloon".gsub(/[aeiou]/, {"a" => "@", "o" => "0"}) # "S@mmy h@s @ rd b@ll00n"
نلاحظ أن ذلك يمنحنا إمكانية إجراء عمليات تبديل معقدة على النصوص والذي يفيدنا في حل بعض المشاكل المعقدة.
الخاتمة
تعرفنا في هذا المقال على العديد من التوابع التي تسمح لنا بالتعامل مع السلاسل النصية باستخدام توابع مبينة مسبقًا لنوع البيانات الخاص بالسلاسل النصية، ومنها ما كان يترك السلسلة الأصلية دون تعديل ومنها من يعدّل عليها.
يعتمد اختيار التوابع التي سنستخدمها على احتياجاتنا، إذ تمنح لغة روبي المبرمجين المرونة لاختيار التوابع التي تفيدهم في العمل مع البيانات الخاصة بهم، وينصح باستخدام التوابع التي لا تعدل على القيمة الأصلية لأنها أسهل في تطوير البرامج وتجنب الأخطاء.
لمزيد من التفصيل، ارجع إلى صفحة النوع String في موسوعة حسوب.
ترجمة -وبتصرف- للمقال How To Work with String Methods in Ruby لصاحبه Brian Hogan.
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.