كيفية تمرير ومعالجة وسائط سطر الأوامر في Rust؟
\n\nكل من كتب أدوات سطر أوامر في Python يعرف مدى سهولة الحصول على المعاملات عبر sys.argv. ولكن عندما تنتقل إلى Rust - لغة البرمجة النظامية التي تعد بالسرعة والأمان - يظهر سؤال منطقي: "How can I access command line parameters in Rust?"
هذا السؤال هو من أكثر الأسئلة شيوعاً على Stack Overflow (عشرات الآلاف من المشاهدات)، وليس من دون سبب. تقدم Rust ليس نهجاً واحداً، بل ثلاثة أساليب رئيسية للعمل مع وسائط سطر الأوامر. من الأبسط std::env::args() إلى المكتبات القوية مثل clap و structopt. في هذه المقالة سنشرح كل منها بأمثلة عملية، لتتمكن من اختيار الأداة المناسبة لمهمتك.
لماذا هذا مهم؟
\nالقدرة على العمل مع وسائط سطر الأوامر هي مهارة أساسية لأي مطور Rust. بدونها لا يمكن إنشاء:
\n- \n
- أدوات CLI (مثل بديل لـ grep, find أو سكريبت نشر خاص بك); \n
- تطبيقات خادم مع إعدادات عبر أعلام التشغيل; \n
- أدوات للأتمتة و DevOps. \n
لنبدأ بأبسط طريقة، ثم ننتقل تدريجياً إلى الحلول الاحترافية.
\n\nالطريقة 1: std::env::args() - النهج البسيط
\n\nأبسط طريقة للحصول على وسائط سطر الأوامر في Rust هي استخدام الدالة القياسية std::env::args(). تقوم بإرجاع مكرر على النصوص، حيث العنصر الأول هو المسار إلى الملف التنفيذي، والباقي هي المعاملات المُمررة.
use std::env;\n\nfn main() {\n let args: Vec<String> = env::args().collect();\n \n // الوسيط الأول هو دائماً اسم البرنامج\n println!("مسار البرنامج: {}", args[0]);\n \n // الباقي هي وسائط المستخدم\n if args.len() > 1 {\n println!("الوسائط المُمررة:");\n for (i, arg) in args[1..].iter().enumerate() {\n println!(" الوسيط {}: {}", i + 1, arg);\n }\n } else {\n println!("لم يتم تمرير أي وسائط.");\n }\n}\n\nلنشغل برنامجنا:
\n$ cargo run -- hello world 42\nمسار البرنامج: ./target/debug/myapp\nالوسائط المُمررة:\n الوسيط 1: hello\n الوسيط 2: world\n الوسيط 3: 42\n\nالمزايا: كود بسيط، لا تبعيات، تحكم كامل.
\nالعيوب: معالجة يدوية للأعلام (مثل --name أو -v)، عدم وجود التحقق من الأنواع (جميع الوسائط نصوص)، لا يوجد مساعدة مدمجة --help.
هذه الطريقة مناسبة تماماً للنماذج السريعة أو عندما يكون لديك وسيط إجباري واحد فقط. لكن للمشاريع الجادة، يجب النظر في البدائل.
\n\nالبديل مع env::args_os()
\nإذا كنت بحاجة إلى البايتات الخام (مثلاً للعمل مع أسماء ملفات غير UTF-8)، استخدم std::env::args_os(). تقوم بإرجاع OsString بدلاً من String:
use std::env;\nuse std::ffi::OsString;\n\nfn main() {\n let args: Vec<OsString> = env::args_os().collect();\n println!("الوسيط الأول (OsString): {:?}", args[0]);\n}\n\nالطريقة 2: مكتبة clap - التحليل التصريحي
\n\nعندما يكبر المشروع، يصبح التحليل اليدوي للوسائط مصدراً للأخطاء. هنا تأتي المساعدة من clap - أشهر مكتبة للعمل مع سطر الأوامر في نظام Rust البيئي. تسمح بوصف جميع المعاملات والأعلام والأوامر الفرعية بشكل تصريحي.
\n\nأضف إلى Cargo.toml:
[dependencies]\nclap = { version = "4.5", features = ["derive"] }\n\nالآن مثال باستخدام ماكرو derive (الطريقة الموصى بها):
\n\nuse clap::Parser;\n\n/// برنامج بسيط لتوضيح clap\n#[derive(