كيفية استخدام getopts لتحليل خيارات Linux Shell Script
نشرت: 2022-06-25 هل ترغب في أن تتعامل البرامج النصية لـ Linux shell مع خيارات سطر الأوامر والوسيطات بشكل أكثر رشاقة؟ يتيح لك برنامج Bash getopts
المدمج إمكانية تحليل خيارات سطر الأوامر ببراعة — وهو سهل أيضًا. نوضح لك كيف.
نقدم لكم getopts المدمج
يعد تمرير القيم إلى نص Bash أمرًا بسيطًا جدًا. يمكنك استدعاء البرنامج النصي الخاص بك من سطر الأوامر أو من برنامج نصي آخر وتقديم قائمة القيم الخاصة بك خلف اسم البرنامج النصي. يمكن الوصول إلى هذه القيم داخل البرنامج النصي كمتغيرات ، بدءًا $1
للمتغير الأول و $2
للمتغير الثاني وهكذا.
ولكن إذا كنت ترغب في تمرير الخيارات إلى نص برمجي ، فإن الموقف يصبح سريعًا أكثر تعقيدًا. عندما نقول خيارات ، فإننا نعني الخيارات أو العلامات أو المفاتيح التي يمكن لبرامج مثل ls
التعامل معها. مسبوقة بشرطة " -
" وعادة ما تكون بمثابة مؤشر للبرنامج لتشغيل أو إيقاف تشغيل بعض جوانب وظائفه.
يحتوي الأمر ls
على أكثر من 50 خيارًا ، تتعلق بشكل أساسي بتنسيق مخرجاته. يقوم الخيار -X
(فرز حسب الامتداد) بفرز الإخراج أبجديًا حسب امتداد الملف. يسرد الخيار -U
(غير الفرز) حسب ترتيب الدليل.
الخيارات ليست سوى - إنها اختيارية. أنت لا تعرف أي الخيارات - إن وجدت - سيختار المستخدم استخدامها ، ولا تعرف أيضًا الترتيب الذي قد يسردهم فيه في سطر الأوامر. هذا يزيد من تعقيد الكود المطلوب لتحليل الخيارات.
تصبح الأمور أكثر تعقيدًا إذا كانت بعض خياراتك تأخذ وسيطة ، تُعرف باسم وسيطة الخيار ، على سبيل المثال ، يتوقع الخيار ls -w
(العرض) أن يتبعه رقم يمثل أقصى عرض لعرض الناتج. وبالطبع ، قد تقوم بتمرير معلمات أخرى إلى البرنامج النصي الخاص بك والتي هي مجرد قيم بيانات ، وليست خيارات على الإطلاق.
لحسن الحظ ، يتعامل getopts
مع هذا التعقيد نيابة عنك. ولأنه مدمج ، فهو متاح على جميع الأنظمة التي تحتوي على غلاف Bash ، لذلك لا يوجد شيء لتثبيته.
ملاحظة: getopts Not getopt
هناك أداة أقدم تسمى getopt
. هذا برنامج فائدة صغير ، وليس برنامج مدمج. هناك العديد من الإصدارات المختلفة من getopt
مختلفة ، في حين أن getops
المدمج يتبع إرشادات POSIX.
اكتب getopts
اكتب getopt
نظرًا لأن getopt
ليس مدمجًا ، فإنه لا يشترك في بعض المزايا التلقائية التي getopts
، مثل التعامل مع المسافات البيضاء بشكل معقول. باستخدام getopts
، تقوم Bash shell بتشغيل البرنامج النصي الخاص بك وتقوم Bash shell بتحليل الخيار. لا تحتاج إلى استدعاء برنامج خارجي للتعامل مع التحليل.
المفاضلة هي getopts
لا تتعامل مع أسماء الخيارات ذات الشُّرط الطويلة والتنسيقات الطويلة. لذا يمكنك استخدام خيارات بتنسيق مثل -w
ولكن ليس " ---wide-format
." من ناحية أخرى ، إذا كان لديك برنامج نصي يقبل الخيارات -a
و -b
و
، فإن -c
getopts
تتيح لك دمجها مثل -abc
أو -bca
أو -bac
وما إلى ذلك.
نحن نناقش getopts
في هذه المقالة ، لذا تأكد من إضافة الحرف "s" الأخير إلى اسم الأمر.
ذات صلة: كيفية الهروب من المسافات في مسارات الملفات على سطر أوامر Windows
خلاصة سريعة: معالجة قيم المعلمات
لا يستخدم هذا البرنامج النصي خيارات متقطعة مثل -a
أو -b
. يقبل المعلمات "العادية" في سطر الأوامر ويتم الوصول إليها داخل البرنامج النصي كقيم.
#! / بن / باش # احصل على المتغيرات واحدة تلو الأخرى صدى "المتغير الأول: 1 دولار" صدى "المتغير الثاني: 2 دولار" صدى "المتغير الثالث: 3 دولارات" # حلقة من خلال المتغيرات لـ var في " $ @" do صدى "$ var" فعله
يتم الوصول إلى المعلمات داخل البرنامج النصي كمتغيرات $1
أو $2
أو $3
.
انسخ هذا النص في محرر واحفظه كملف يسمى "variables.sh". سنحتاج إلى جعله قابلاً للتنفيذ باستخدام الأمر chmod
. ستحتاج إلى القيام بهذه الخطوة لجميع النصوص التي نناقشها. فقط استبدل اسم ملف البرنامج النصي المناسب في كل مرة.
chmod + x variables.sh
إذا قمنا بتشغيل البرنامج النصي الخاص بنا بدون معلمات ، فسنحصل على هذه النتيجة.
./variables.sh
لم نمرر أي معلمات لذا لا يحتوي النص البرمجي على قيم للإبلاغ عنها. دعنا نقدم بعض المعلمات هذه المرة.
./variables.sh كيفية المهوس
كما هو متوقع ، تم تعيين المتغيرات $1
و $2
و $3
على قيم المعلمات ونراها مطبوعة.
يعني هذا النوع من معالجة المعلمات واحدًا لواحد أننا بحاجة إلى معرفة عدد المعلمات مسبقًا. لا تهتم الحلقة الموجودة في الجزء السفلي من البرنامج النصي بعدد المعلمات الموجودة ، فهي تدور دائمًا عبرها جميعًا.
إذا قدمنا معاملًا رابعًا ، فلن يتم تعيينه إلى متغير ، لكن الحلقة لا تزال تتعامل معه.
./variables.sh كيفية تطوير موقع الويب
إذا وضعنا علامات اقتباس حول كلمتين ، فسيتم التعامل معها كمعامل واحد.
./variables.sh كيفية "المهوس"
إذا كنا سنحتاج إلى البرنامج النصي الخاص بنا للتعامل مع جميع مجموعات الخيارات ، والخيارات مع الوسائط ، ومعلمات نوع البيانات "العادية" ، فسنحتاج إلى فصل الخيارات عن المعلمات العادية. يمكننا تحقيق ذلك بوضع جميع الخيارات - مع أو بدون وسيطات - قبل المعلمات العادية.
لكن دعونا لا نركض قبل أن نتمكن من المشي. لنلقِ نظرة على أبسط حالة للتعامل مع خيارات سطر الأوامر.
خيارات المناولة
نستخدم getopts
في حلقة while
. يعمل كل تكرار للحلقة على خيار واحد تم تمريره إلى البرنامج النصي. في كل حالة ، يتم تعيين المتغير OPTION
على الخيار المحدد بواسطة getopts
.
مع كل تكرار للحلقة ، ينتقل getopts
إلى الخيار التالي. عندما لا يكون هناك المزيد من الخيارات ، ترجع getopts
false
وتخرج حلقة while
.
تتم مطابقة متغير OPTION
مع الأنماط الموجودة في كل من عبارات بيان الحالة. نظرًا لأننا نستخدم بيان الحالة ، فلا يهم الترتيب الذي يتم توفير الخيارات في سطر الأوامر. يتم إسقاط كل خيار في بيان الحالة ويتم تشغيل الجملة المناسبة.
الجمل الفردية في بيان الحالة تجعل من السهل تنفيذ الإجراءات الخاصة بالخيار داخل النص البرمجي. عادةً ، في نص برمجي في العالم الحقيقي ، ستقوم بتعيين متغير في كل جملة ، وستعمل هذه كعلامات إضافية في البرنامج النصي ، مما يسمح ببعض الوظائف أو يرفضها.
انسخ هذا النص في محرر واحفظه كبرنامج نصي يسمى "options.sh" ، واجعله قابلاً للتنفيذ.
#! / بن / باش بينما خيار getopts 'abc' ؛ فعل الحالة "$ OPTION" في أ) صدى "الخيار مستخدم" ؛؛ ب) صدى "الخيار ب المستخدم" ؛؛ ج) صدى "الخيار ج المستخدم" ؛؛ ؟) صدى "Usage: $ (basename $ 0) [-a] [-b] [-c]" خروج 1 ؛؛ esac فعله
هذا هو الخط الذي يحدد حلقة while.
بينما خيار getopts 'abc' ؛ فعل
يتبع الأمر getopts
سلسلة الخيارات . هذا يسرد الحروف التي سنستخدمها كخيارات. يمكن استخدام الأحرف في هذه القائمة فقط كخيارات. لذلك في هذه الحالة ، سيكون -d
غير صالح. هذا من شأنه أن يقع في شرك ?)
جملة لأن getopts
تُرجع علامة استفهام " ?
"لخيار غير محدد. إذا حدث ذلك ، تتم طباعة الاستخدام الصحيح في نافذة الجهاز:
صدى "Usage: $ (basename $ 0) [-a] [-b] [-c]"
حسب الاصطلاح ، فإن التفاف خيار بين قوسين " []
" في هذا النوع من رسائل الاستخدام الصحيحة يعني أن الخيار اختياري. يزيل الأمر basename أي مسارات دليل من اسم الملف. اسم ملف البرنامج النصي محتجز في $0
في نصوص Bash النصية.
دعنا نستخدم هذا البرنامج النصي مع مجموعات سطر أوامر مختلفة.
./options.sh -a
./options.sh -a -b -c
./options.sh -ab -c
./options.sh -cab
كما نرى ، يتم تحليل جميع مجموعات خيارات الاختبار لدينا ومعالجتها بشكل صحيح. ماذا لو جربنا خيارًا غير موجود؟
./options.sh -d
يتم تشغيل شرط الاستخدام ، وهو أمر جيد ، لكننا نحصل أيضًا على رسالة خطأ من الصدفة. قد يكون أو لا يهم في حالة الاستخدام الخاصة بك. إذا كنت تستدعي البرنامج النصي من برنامج نصي آخر يجب عليه تحليل رسائل الخطأ ، فسيزيد الأمر صعوبة إذا كانت الصدفة تولد رسائل خطأ أيضًا.
يعد إيقاف تشغيل رسائل خطأ shell أمرًا سهلاً للغاية. كل ما نحتاج إلى القيام به هو وضع علامة النقطتين " :
" كأول حرف في سلسلة الخيارات.
إما أن تقوم بتحرير ملف "options.sh" وأضف نقطتين كحرف أول من سلسلة الخيارات ، أو احفظ هذا البرنامج النصي باسم "options2.sh" ، واجعله قابلاً للتنفيذ.
#! / بن / باش بينما getopts ': abc' OPTION ؛ فعل الحالة "$ OPTION" في أ) صدى "خيار مستعمل" ؛؛ ب) صدى "الخيار ب المستخدم" ؛؛ ج) صدى "الخيار ج المستخدم" ؛؛ ؟) صدى "Usage: $ (basename $ 0) [-a] [-b] [-c]" خروج 1 ؛؛ esac فعله
عندما نقوم بتشغيل هذا وإنشاء خطأ ، فإننا نتلقى رسائل الخطأ الخاصة بنا دون أي رسائل shell.
./options2.sh.sh -d
استخدام getopts مع وسيطات الخيار
لإخبار getopts
أن الخيار سيتبعه وسيطة ، ضع علامة النقطتين " :
" مباشرةً خلف حرف الخيار في سلسلة الخيارات.
إذا اتبعنا "b" و "c" في سلسلة الخيارات مع النقطتين ، getopt
وسيطات لهذه الخيارات. انسخ هذا النص في المحرر الخاص بك واحفظه باسم "arguments.sh" واجعله قابلاً للتنفيذ.
تذكر أن النقطتين الأولى في سلسلة الخيارات تُستخدم لمنع رسائل خطأ الصدفة - ولا علاقة لها بمعالجة الوسيطة.
عندما تعالج getopt
خيارًا باستخدام وسيطة ، يتم وضع الوسيطة في متغير OPTARG
. إذا كنت تريد استخدام هذه القيمة في مكان آخر في البرنامج النصي الخاص بك ، فستحتاج إلى نسخها إلى متغير آخر.
#! / بن / باش بينما getopts ': ab: c:' OPTION ؛ فعل الحالة "$ OPTION" في أ) صدى "خيار مستعمل" ؛؛ ب) argB = "$ OPTARG" صدى "الخيار ب المستخدم مع: $ argB" ؛؛ ج) argC = "$ OPTARG" صدى "الخيار c يُستخدم مع: $ argC" ؛؛ ؟) صدى "Usage: $ (basename $ 0) [-a] [-bإلى] [-c وسيطة]" خروج 1 ؛؛ esac فعله
دعونا نجري ذلك ونرى كيف يعمل.
./arguments.sh -a -b "كيفية المهوس" -c reviewgeek
./arguments.sh -c reviewgeek -a
لذا يمكننا الآن التعامل مع الخيارات مع أو بدون وسيطات ، بغض النظر عن الترتيب الذي يتم تقديمه به في سطر الأوامر.
لكن ماذا عن البارامترات العادية؟ قلنا سابقًا أننا علمنا أنه يتعين علينا وضع هؤلاء في سطر الأوامر بعد أي خيارات. دعونا نرى ماذا سيحدث إذا فعلنا ذلك.
خيارات المزج والمعلمات
سنقوم بتغيير البرنامج النصي السابق ليشمل سطرًا إضافيًا. عندما تنتهي حلقة while
loop ويتم التعامل مع جميع الخيارات ، سنحاول الوصول إلى المعلمات العادية. سنطبع القيمة $1
.
احفظ هذا البرنامج النصي باسم "arguments2.sh" ، واجعله قابلاً للتنفيذ.
#! / بن / باش بينما getopts ': ab: c:' OPTION ؛ فعل الحالة "$ OPTION" في أ) صدى "خيار مستعمل" ؛؛ ب) argB = "$ OPTARG" صدى "الخيار ب المستخدم مع: $ argB" ؛؛ ج) argC = "$ OPTARG" صدى "الخيار c يُستخدم مع: $ argC" ؛؛ ؟) صدى "Usage: $ (basename $ 0) [-a] [-bإلى] [-c وسيطة]" خروج 1 ؛؛ esac فعله صدى "المتغير هو: $ 1"
سنحاول الآن مجموعة قليلة من الخيارات والمعلمات.
./arguments2.sh ديف
./arguments2.sh -a ديف
./arguments2.sh -a -c how-to-geek ديف
حتى الآن يمكننا أن نرى المشكلة. بمجرد استخدام أي خيارات ، تمتلئ المتغيرات $1
فصاعدًا بأعلام الخيارات ومعاملاتها. في المثال الأخير ، سيحتفظ $4
بقيمة المعلمة "dave" ، ولكن كيف يمكنك الوصول إلى ذلك في البرنامج النصي الخاص بك إذا كنت لا تعرف عدد الخيارات والوسيطات التي سيتم استخدامها؟
الإجابة هي استخدام OPTIND
والأمر shift
.
يتجاهل الأمر shift
المعلمة الأولى - بغض النظر عن النوع - من قائمة المعلمات. المعلمات الأخرى "shuffle down" ، لذا فإن المعلمة 2 تصبح المعلمة 1 ، المعلمة 3 تصبح المعلمة 2 ، وهكذا. وهكذا يصبح $ $2
$1
، $3
$2
أمريكية ، وهكذا.
إذا قمت بتوفير shift
برقم ، فسيتم إزالة العديد من المعلمات من القائمة.
يحسب OPTIND
الخيارات والوسيطات كما تم العثور عليها ومعالجتها. بمجرد معالجة جميع الخيارات OPTIND
، سيكون OPTIND أعلى من عدد الخيارات. لذلك إذا استخدمنا shift لتقطيع معلمات (OPTIND-1)
من قائمة المعلمات ، فسنبقى مع المعلمات العادية في $1
فصاعدًا.
هذا بالضبط ما يفعله هذا البرنامج النصي. احفظ هذا البرنامج النصي باسم "arguments3.sh" واجعله قابلاً للتنفيذ.
#! / بن / باش بينما getopts ': ab: c:' OPTION ؛ فعل الحالة "$ OPTION" في أ) صدى "خيار مستعمل" ؛؛ ب) argB = "$ OPTARG" صدى "الخيار ب المستخدم مع: $ argB" ؛؛ ج) argC = "$ OPTARG" صدى "الخيار c يُستخدم مع: $ argC" ؛؛ ؟) صدى "Usage: $ (basename $ 0) [-a] [-bإلى] [-c وسيطة]" خروج 1 ؛؛ esac فعله صدى "قبل - المتغير الأول هو: $ 1" تحول "$ (($ OPTIND -1))" صدى "بعد - المتغير الأول هو: $ 1" صدى "بقية الحجج (المعاملات)" لـ x في "$ @" فعل صدى $ x فعله
سنقوم بتشغيل هذا بمزيج من الخيارات والوسيطات والمعلمات.
./arguments3.sh -a -c How-to-Geek "ديف دي" dozy beaky mick tich
يمكننا أن نرى أنه قبل أن نطلق على shift
، كان $1
يحمل "-a" ، ولكن بعد الأمر shift ، يحمل $1
معلمة non-option ، بدون وسيطة. يمكننا إجراء حلقة عبر جميع المعلمات بنفس السهولة التي يمكننا بها في برنامج نصي بدون تحليل خيار.
من الجيد دائمًا أن يكون لديك خيارات
لا تحتاج خيارات المعالجة وحججها في البرامج النصية إلى التعقيد. باستخدام getopts
يمكنك إنشاء نصوص برمجية تتعامل مع خيارات سطر الأوامر والوسيطات والمعلمات تمامًا مثل البرامج النصية الأصلية المتوافقة مع POSIX.