سؤال

ركضت إلى ss64.com الذي يوفر مساعدة جيدة فيما يتعلق بكيفية كتابة البرامج النصية الدُفعات التي سيتم تشغيل مترجم أوامر Windows.

ومع ذلك ، لم أتمكن من إيجاد تفسير جيد لـ قواعد من البرامج النصية الدُفعات ، كيف تتوسع الأشياء أو لا تتوسع ، وكيفية الهروب من الأشياء.

فيما يلي عينة أسئلة لم أتمكن من حلها:

  • كيف يتم إدارة نظام الاقتباس؟ انا صنعت Tinyperl النصي
    ( foreach $i (@ARGV) { print '*' . $i ; } ) ، جمعها ودعاها بهذه الطريقة:
    • my_script.exe "a ""b"" c" → الإخراج هو *a "b*c
    • my_script.exe """a b c""" → إخراجها *"a*b*c"
  • كيف يكون الداخلية echo عمل القيادة؟ ما الذي يتم توسيعه داخل هذا الأمر؟
  • لماذا يجب علي استخدام for [...] %%I في البرامج النصية للملفات ، ولكن for [...] %I في الجلسات التفاعلية؟
  • ما هي شخصيات الهروب ، وفي أي سياق؟ كيف تهرب من علامة في المئة؟ على سبيل المثال ، كيف يمكنني الصدى %PROCESSOR_ARCHITECTURE% حرفيا؟ لقد وجدت ذلك echo.exe %""PROCESSOR_ARCHITECTURE% يعمل ، هل هناك حل أفضل؟
  • كيف تفعل أزواج % مباراة؟ مثال:
    • set b=a , echo %a %b% c%%a a c%
    • set a =b, echo %a %b% c%bb c%
  • كيف يمكنني التأكد من أن المتغير يمر إلى أمر كوسيطة واحدة إذا كان هذا المتغير يحتوي على علامات اقتباس مزدوجة؟
  • كيف يتم تخزين المتغيرات عند استخدام set يأمر؟ على سبيل المثال ، إذا فعلت set a=a" b وثم echo.%a% استنتج a" b. إذا كنت أستخدم echo.exe من unxules ، أحصل a b. كيف حدث %a% يتوسع بطريقة مختلفة؟

شكرا لك على أضواءك.

هل كانت مفيدة؟

المحلول

أجرينا تجارب للتحقيق في قواعد النصوص الدُفعات. قمنا أيضًا بالتحقيق في الاختلافات بين وضع الدُفعات ووضع خط الأوامر.

محلل خط الدُفعات:

فيما يلي نظرة عامة موجزة على المراحل التي ينطوي عليها معالجة سطر رمز في ملف الدُفعة:

المرحلة 0) خط قراءة:

المرحلة 1) التوسع في المئة:

المرحلة 1.5) إزالة <CR>: قم بإزالة جميع أحرف إرجاع النقل (0x0D)

المرحلة 2) معالجة الأحرف الخاصة ، والرمز ، وإنشاء كتلة الأوامر المخزنة مؤقتًا: هذه عملية معقدة تتأثر بأشياء مثل عروض الأسعار والشخصيات الخاصة والرموز الرمزية ، وتهرب من Caret.

المرحلة 3) صدى الأوامر (الأوامر) المتوفرة فقط إذا لم تبدأ كتلة الأوامر بـ @, ، وكان الصدى في بداية الخطوة السابقة.

المرحلة 4) ل %X التوسع المتغير: فقط إذا كان الأمر AT نشطًا وتم معالجة الأوامر بعد DO.

المرحلة 5) التوسع المتأخر: فقط إذا تم تمكين التوسع المتأخر

المرحلة 5.3) معالجة الأنابيب: فقط إذا كانت الأوامر على جانبي الأنبوب

المرحلة 5.5) تنفيذ إعادة التوجيه:

المرحلة 6) معالجة المكالمات/مضاعفة الذبابة: فقط إذا كان رمز الأمر هو المكالمة

المرحلة 7) التنفيذ: يتم تنفيذ الأمر


فيما يلي تفاصيل لكل مرحلة:

لاحظ أن المراحل الموضحة أدناه ليست سوى نموذج لكيفية عمل محلل الدُفعة. قد لا يعكس CMD.exe الداخلي الفعلي هذه المراحل. لكن هذا النموذج فعال في التنبؤ بسلوك البرامج النصية الدُفعات.

المرحلة 0) خط قراءة: قراءة سطر الإدخال من خلال أولا <LF>.

  • عند قراءة خط ليتم تحليله كقيادة ، <Ctrl-Z> (0x1a) تتم قراءة باسم <LF> (Linefeed 0x0a)
  • عندما يقرأ Goto أو Call خطوط أثناء المسح الضوئي لـ A: Label ، <Ctrl-Z>, ، يعامل بنفسه - هو كذلك ليس تحول إلى <LF>

المرحلة 1) التوسع في المئة:

  • مزدوج %% يتم استبداله بأحد %
  • توسيع الحجج (%*, %1, %2, ، إلخ.)
  • التوسع في %var%, ، إذا لم يكن Var موجودًا ، استبدله بأي شيء
  • يتم اقتطاع الخط في البداية <LF> ليس داخل %var% توسع
  • للحصول على شرح كامل ، اقرأ النصف الأول من هذا من Dbenham نفس الموضوع: مرحلة النسبة المئوية

المرحلة 1.5) إزالة <CR>: قم بإزالة جميع إرجاع النقل (0x0D) من الخط

المرحلة 2) معالجة الأحرف الخاصة ، والرمز ، وإنشاء كتلة الأوامر المخزنة مؤقتًا: هذه عملية معقدة تتأثر بأشياء مثل عروض الأسعار والشخصيات الخاصة والرموز الرمزية ، وتهرب من Caret. ما يلي هو تقريب هذه العملية.

هناك مفاهيم مهمة طوال هذه المرحلة.

  • الرمز المميز هو ببساطة سلسلة من الأحرف التي يتم التعامل معها كوحدة.
  • يتم فصل الرموز بواسطة المحددات الرمزية. المحددات الرمزية القياسية <space> <tab> ; , = <0x0B> <0x0C> و <0xFF>
    يتم التعامل مع المحددات الرمزية المتتالية على أنها واحدة - لا توجد رموز فارغة بين المحددات الرمزية
  • لا يوجد محددات رمزية داخل سلسلة مقتبسة. يتم التعامل مع السلسلة المقتبسة بأكملها دائمًا كجزء من رمز واحد. قد يتكون رمز واحد من مزيج من السلاسل المقتبسة والشخصيات غير المؤهلة.

قد يكون للأحرف التالية معنى خاص في هذه المرحلة ، اعتمادًا على السياق: ^ ( @ & | < > <LF> <space> <tab> ; , = <0x0B> <0x0C> <0xFF>

انظر إلى كل حرف من اليسار إلى اليمين:

  • إذا كانت سيارة مياه (^) ، يتم هروب الشخصية التالية ، ويتم إزالة الكاريت الهرب. الشخصيات التي هربت تفقد كل المعنى الخاص (باستثناء <LF>).
  • إذا كان اقتباسًا (") ، تبديل علم الاقتباس. إذا كانت علامة الاقتباس نشطة ، فحينئذ فقط " و <LF> هي خاصة. تفقد جميع الشخصيات الأخرى معناها الخاص حتى يقوم الاقتباس التالي بتبديل علامة الاقتباس. لا يمكن الهروب من الاقتباس الختامي. جميع الشخصيات المقتبسة هي دائمًا في نفس الرمز المميز.
  • <LF> دائمًا ما يؤدي إلى إيقاف علم الاقتباس. تختلف السلوكيات الأخرى اعتمادًا على السياق ، لكن اقتباسات لا تغير أبدًا سلوك <LF>.
    • هرب <LF>
      • <LF> تم تجريده
      • يتم هروب الشخصية التالية. إذا كان في نهاية المخزن المؤقت في نهاية الخط ، يتم قراءة السطر التالي ومعالجته بواسطة المرحلتين 1 و 1.5 وملحق الخط الحالي قبل الهروب من الحرف التالي. إذا كانت الشخصية التالية <LF>, ثم يتم التعامل معها على أنها حرفية ، وهذا يعني أن هذه العملية ليست عودية.
    • غير متككلين <LF> ليس ضمن الأقواس
      • <LF> تم تجريده وإنهاء تحليل الخط الحالي.
      • يتم تجاهل أي شخصيات متبقية في المخزن المؤقت الخط ببساطة.
    • غير متككلين <LF> ضمن A في كتلة الأقواس
      • <LF> يتم تحويله إلى أ <space>
      • إذا كان في نهاية المخزن المؤقت للخط ، يتم قراءة السطر التالي وإلحاقه بالذات الحالية.
    • غير متككلين <LF> ضمن كتلة الأوامر الأقواس
      • <LF> يتم تحويله إلى <LF><space>, ، و ال <space> يعامل كجزء من السطر التالي من كتلة الأوامر.
      • إذا كان في نهاية المخزن المؤقت في نهاية الخط ، يتم قراءة السطر التالي وإلحاقه بالمساحة.
  • إذا كانت واحدة من الشخصيات الخاصة & | < أو >, ، تقسيم الخط في هذه المرحلة من أجل التعامل مع الأنابيب ، وتسلسل الأوامر ، وإعادة التوجيه.
    • في حالة أنبوب (|) ، كل جانب هو أمر منفصل (أو كتلة أوامر) يحصل على معالجة خاصة في المرحلة 5.3
    • في حالة ما اذا &, &&, ، أو || تسلسل القيادة ، يتم التعامل مع كل جانب من جانب التسلسل كأمر منفصل.
    • في حالة ما اذا <, <<, >, ، أو >> إعادة التوجيه ، يتم تحليل شرط إعادة التوجيه ، وإزالته مؤقتًا ، ثم تم إلحاقه بنهاية الأمر الحالي. يتكون شرط إعادة التوجيه من رقم مقبض الملف الاختياري ، ومشغل إعادة التوجيه ، ورمز وجهة إعادة التوجيه.
      • إذا كان الرمز المميز الذي يسبق مشغل إعادة التوجيه رقمًا واحدًا ، فإن الرقم يحدد مقبض الملف المراد إعادة توجيهه. إذا لم يتم العثور على رمز المقبض ، فإن إخراج إعادة توجيه الإعدادات الافتراضية إلى 1 (stdout) ، وإعادة توجيه الإدخال الافتراضي إلى 0 (stdin).
  • إذا بدأ الرمز المميز الأول لهذا الأمر (قبل نقل إعادة التوجيه إلى النهاية) @, ، ثم @ له معنى خاص. ((@ ليس خاصًا في أي سياق آخر)
    • الخاص @ تم حذفه.
    • إذا كان Echo قيد التشغيل ، فسيتم استبعاد هذا الأمر ، إلى جانب أي أوامر متسلسلة التالية على هذا الخط ، من المرحلة 3 Echo. إذا @ قبل الافتتاح (, ، ثم يتم استبعاد كتلة الأقواس بأكملها من المرحلة 3 صدى.
  • أقواس العملية (ينص على عبارات مركبة عبر خطوط متعددة):
    • إذا كان المحلل لا يبحث عن رمز أمر ، فعندئذٍ ( ليس مميزًا.
    • إذا كان المحلل يبحث عن رمز القيادة ويجد (, ، ثم ابدأ بيان مركب جديد وزيادة عداد قوسين
    • إذا كان عداد الأقواس> 0 ثم ) ينهي بيان المركب ويقلل من عداد الأقواس.
    • إذا تم الوصول إلى نهاية الخط وكان عداد الأقواس> 0 ، فسيتم إلحاق السطر التالي ببيان المركب (يبدأ مرة أخرى بالمرحلة 0)
    • إذا كان عداد الأقواس 0 ويبحث المحلل ) وظائف مماثلة ل REM بيان طالما يتبعه على الفور محدد رمزي أو شخصية خاصة أو سطر جديد أو نهاية الملف
      • جميع الشخصيات الخاصة تفقد معناها إلا ^ (تسلسل الخط ممكن)
      • بمجرد الوصول إلى نهاية الخط المنطقي ، يتم التخلص من "الأمر" بأكمله.
  • يتم تحليل كل أمر في سلسلة من الرموز. يتم التعامل دائمًا مع الرمز المميز الأول كرمز للمجموعة (بعد خاص @ تم تجريدها وانتقلت إعادة التوجيه إلى النهاية).
    • يتم تجريد محددات الرمز المميز قبل الرمز المميز
    • عند تحليل رمز الأمر ، ( وظائف كوحد رمز الرمز المميز ، بالإضافة إلى المحددات الرمزية القياسية
    • يعتمد التعامل مع الرموز اللاحقة على الأمر.
  • معظم الأوامر ببساطة تسلس جميع الوسائط بعد رمز الأوامر في رمز وسيطة واحدة. يتم الحفاظ على جميع محددات الرمز المميز للحجة. لا يتم تحليل خيارات الحجة عادة حتى المرحلة 7.
  • ثلاثة أوامر تحصل على معالجة خاصة - إذا ، و ، ريم
    • إذا تم تقسيمها إلى جزءين أو ثلاثة أجزاء متميزة تتم معالجتها بشكل مستقل. سيؤدي خطأ بناء الجملة في IF Construction إلى خطأ في بناء الجملة المميت.
      • عملية المقارنة هي الأمر الفعلي الذي يتدفق طوال الطريق إلى المرحلة 7
        • كل شيء إذا تم تحليل الخيارات بالكامل في المرحلة 2.
        • تنهار المحددات الرمزية المتتالية في مساحة واحدة.
        • اعتمادًا على مشغل المقارنة ، سيكون هناك واحد أو اثنين من الرموز المميزة التي تم تحديدها.
      • كتلة الأوامر الحقيقية هي مجموعة الأوامر بعد الشرط ، ويتم تحليلها مثل أي كتلة أوامر أخرى. إذا تم استخدام آخر ، فيجب أن تكون الكتلة الحقيقية أقواس.
      • كتلة الأوامر الخاطئة الاختيارية هي مجموعة الأوامر بعد آخر. مرة أخرى ، يتم تحليل كتلة القيادة هذه بشكل طبيعي.
      • لا تتدفق كتل الأوامر الحقيقية والخطأ تلقائيًا إلى المراحل اللاحقة. تتم التحكم في معالجتها اللاحقة في المرحلة 7.
    • لانقسام في اثنين بعد القيام به. سيؤدي خطأ بناء الجملة في البناء إلى خطأ في بناء الجملة المميت.
      • الجزء من خلال DO هو أمر التكرار الفعلي الذي يتدفق طوال المرحلة 7
        • يتم تحليل كل الخيارات بالكامل في المرحلة 2.
        • يعامل جملة الأقواس <LF> كما <space>. بعد تحليل البند في ، يتم تسلسل جميع الرموز المميزة معًا لتشكيل رمز واحد.
        • تنهار محددات الرمز المميز غير المكشوفة/غير المقيدة على التوالي في مساحة واحدة في جميع أنحاء الأمر من خلال DO.
      • الجزء بعد القيام به هو كتلة قيادة يتم تحليلها بشكل طبيعي. يتم التحكم في المعالجة اللاحقة لكتلة القيادة عن طريق التكرار في المرحلة 7.
    • يتم التعامل مع REM في المرحلة 2 بشكل كبير عن جميع الأوامر الأخرى.
      • يتم تحليل رمز حجة واحد فقط - يتجاهل المحلل الشخصي الشخصيات بعد رمز الوسيطة الأولى.
      • قد يظهر أمر REM في الإخراج في المرحلة الثالثة ، ولكن لا يتم تنفيذ الأمر مطلقًا ، ويتم صدى نص الوسيطة الأصلي - لم تتم إزالة الكآبة الهاربة ، باستثناء ...
        • إذا كان هناك رمز حجة واحد فقط ينتهي بتكييف غير مسبوق ^ هذا ينهي الخط ، ثم يتم إلقاء رمز الوسيطة بعيدا ، ويتم تحليل الخط اللاحق وملحق REM. يتكرر هذا حتى يكون هناك أكثر من رمز واحد ، أو أن الشخصية الأخيرة ليست ^.
  • إذا بدأ الرمز المميز :, ، وهذه هي الجولة الأولى من المرحلة 2 (وليس إعادة التشغيل بسبب الدعوة في المرحلة 6)
    • عادة ما يتم التعامل مع الرمز المميز على أنه تسمية غير متوفرة.
      • ومع ذلك ، يتم تحليل ما تبقى من الخط ), <, >, & و | لم يعد لديه معنى خاص. يعتبر الباقي بأكمله من الخط جزءًا من التسمية "الأمر".
      • ال ^ لا يزال مميزًا ، مما يعني أنه يمكن استخدام استمرار الخط لإلحاق الخط اللاحق بالعلامة.
      • و تسمية غير متوفرة ضمن كتلة أقواس سيؤدي إلى خطأ في بناء الجملة المميت ما لم يتبعه على الفور أمر أو علامة تنفيذ على السطر التالي.
        • ( لم يعد لديه معنى خاص للأمر الأول الذي يتبع تسمية غير متوفرة.
      • يتم إحباط الأمر بعد اكتمال تحليل التسمية. لا تحدث المراحل اللاحقة للتسمية
    • هناك ثلاثة استثناءات يمكن أن تتسبب في معاملة تسمية في المرحلة 2 على أنها علامة تنفيذ يستمر التحليل خلال المرحلة 7.
      • هناك إعادة توجيه تسبق رمز التسمية ، وهناك أ | أنبوب أو &, &&, ، أو || تسلسل القيادة على الخط.
      • هناك إعادة توجيه يسبق رمز التسمية ، والأمر داخل كتلة أقواس.
      • رمز التسمية هو أول أمر على سطر داخل كتلة أقواس ، وانتهى السطر أعلاه مع تسمية غير متوفرة.
    • يحدث التالي عندما علامة تنفيذ تم اكتشافه في المرحلة 2
      • يتم استبعاد التسمية ، والوسائط الخاصة بها ، وإعادة توجيهها من أي ناتج صدى في المرحلة 3
      • يتم تحليل أي أوامر متسلسلة لاحقة على الخط وتنفيذها بالكامل.
    • لمزيد من المعلومات حول علامات تنفيذ ضد. تسميات غير متوقعة, ، نرى https://www.dostips.com/forum/viewtopic.php؟f=3&t=3803&p=55405#p55405

المرحلة 3) صدى الأوامر (الأوامر) المتوفرة فقط إذا لم تبدأ كتلة الأوامر بـ @, ، وكان الصدى في بداية الخطوة السابقة.

المرحلة 4) ل %X التوسع المتغير: فقط إذا كان الأمر AT نشطًا وتم معالجة الأوامر بعد DO.

  • في هذه المرحلة ، سيتم تحويل المرحلة الأولى من معالجة الدُفعات بالفعل إلى متغير مثل %%X داخل %X. يحتوي سطر الأوامر على قواعد توسيع مختلفة في المئة للمرحلة 1. وهذا هو السبب في استخدام خطوط الأوامر %X لكن ملفات الدُفعات تستخدم %%X للمتغيرات.
  • بالنسبة للأسماء المتغيرة حساسة للحالة ، ولكن ~modifiers ليست حساسة للحالة.
  • ~modifiers أخذ الأسبقية على أسماء متغيرة. إذا كانت هناك شخصية تتبع ~ هو معدل وصالح للاسم المتغير ، وهناك حرف لاحق نشط للاسم المتغير ، ثم يتم تفسير الحرف على أنه تعديل.
  • بالنسبة للأسماء المتغيرة عالمية ، ولكن فقط في سياق شرط DO. إذا تم استدعاء روتين من داخل جملة DO ، فلا يتم توسيع المتغيرات للمتغيرات داخل الروتين المسمى. ولكن إذا كان لدى الروتين أمره الخاص ، فعندئذٍ الكل يمكن الوصول حاليًا للمتغيرات إلى أوامر DO الداخلية.
  • للأسماء المتغيرة يمكن إعادة استخدامها داخل FORS المتداخلة. الأسبقية الداخلية للقيمة لها الأسبقية ، ولكن بمجرد إغلاق الداخلية ، يتم استعادة الخارجي للقيمة.
  • إذا كان ECHO في بداية هذه المرحلة ، يتم تكرار المرحلة 3) لإظهار أوامر DO المحلية بعد توسيع المتغيرات للمتغيرات.

---- من هذه النقطة فصاعدًا ، تتم معالجة كل أمر تم تحديده في المرحلة 2 بشكل منفصل.
---- يتم الانتهاء من المراحل من 5 إلى 7 لأمر واحد قبل الانتقال إلى التالي.

المرحلة 5) التوسع المتأخر: فقط إذا كان التوسع المتأخر قيد التشغيل ، فإن الأمر ليس في كتلة أقواس على جانبي الأنبوب, ، والأمر ليس سيناريو "عاري" (اسم البرنامج النصي بدون أقواس أو الاتصال أو تسلسل الأوامر أو الأنابيب).

  • يتم تحليل كل رمز لأمر لتأخير التوسع بشكل مستقل.
    • معظم الأوامر تحليل اثنين أو أكثر من الرموز الرموز - رمز الأوامر ، الرمز المميز للوسائط ، وكل رمز وجهة إعادة توجيه.
    • for command يخلع رمز البند فقط.
    • يقوم الأمر if بتجديد قيم المقارنة فقط - إما واحدة أو اثنين ، اعتمادًا على مشغل المقارنة.
  • لكل رمز مميز ، تحقق أولاً مما إذا كان يحتوي على أي شيء !. إذا لم يكن الأمر كذلك ، فإن الرمز المميز غير محلل - مهم ل ^ الشخصيات. إذا كان المميز يحتوي !, ، ثم مسح كل حرف من اليسار إلى اليمين:
    • إذا كانت سيارة مياه (^) الشخصية التالية ليس لها معنى خاص ، تتم إزالة الكاريت نفسها
    • إذا كانت علامة تعجب ، فابحث عن علامة التعجب التالية (لم يتم ملاحظة الكاريت بعد الآن) ، فتوسيع إلى قيمة المتغير.
      • الافتتاح المتتالي ! انهارت في واحدة !
      • أي غير متبق ! تم حذفه
    • يعد توسيع نطاق Vars في هذه المرحلة "آمنًا" ، لأنه لم يعد يتم اكتشاف الشخصيات الخاصة (حتى <CR> أو <LF>)
    • للحصول على شرح أكثر اكتمالا ، اقرأ النصف الثاني من هذا من DBENHAMنفس الموضوع - مرحلة نقطة التعجب

المرحلة 5.3) معالجة الأنابيب: فقط إذا كانت الأوامر على جانبي الأنبوب
تتم معالجة كل جانب من الأنبوب بشكل مستقل وبشكل غير متزامن.

  • إذا كان الأمر داخليًا لـ cmd.exe ، أو أنه ملف دفعي ، أو إذا كان كتلة أمر أقواس ، فسيتم تنفيذه في مؤشر ترابط cmd.exe جديد عبر %comspec% /S /D /c" commandBlock", ، لذلك تحصل كتلة الأوامر على إعادة تشغيل المرحلة ، ولكن هذه المرة في وضع سطر الأوامر.
    • إذا كان كتلة الأوامر أقواس ، ثم كل شيء <LF> مع أمر قبل وبعد يتم تحويله إلى <space>&. آخر <LF> تم تجريدهم.
  • هذه هي نهاية المعالجة لأوامر الأنابيب.
  • نرى لماذا يفشل التوسع المتأخر عندما داخل كتلة من الكود؟ لمعرفة المزيد عن تحليل الأنابيب والمعالجة

المرحلة 5.5) تنفيذ إعادة التوجيه: يتم الآن تنفيذ أي إعادة توجيه تم اكتشافها في المرحلة الثانية.

المرحلة 6) معالجة المكالمات/مضاعفة الذبابة: فقط إذا كان رمز الأمر هو المكالمة ، أو إذا كان النص قبل أول محدد الرمز المميز القياسي الذي يحدث. إذا تم تحليل المكالمة من رمز أمر أكبر ، فسيتم إعداد الجزء غير المستخدم إلى الرمز المميز للوسائط قبل المتابعة.

  • مسح الرمز المميز للوسيطات لمجلة /?. إذا تم العثور عليها في أي مكان داخل الرموز ، فقم بإحباط المرحلة 6 وانتقل إلى المرحلة 7 ، حيث سيتم طباعة مساعدة المكالمة.
  • إزالة الأول CALL, ، لذلك يمكن تكديس مكالمات متعددة
  • مضاعفة جميع carets
  • إعادة تشغيل المراحل 1 و 1.5 و 2 ، ولكن لا تستمر في المرحلة 3
    • يتم تقليل أي كاريت مضاعفة مرة أخرى إلى سيارة إلكترونية واحدة طالما لم يتم اقتباسها. ولكن لسوء الحظ ، لا تزال الكاريت المقتبسة مضاعفة.
    • تتغير المرحلة الأولى قليلاً
      • أخطاء التوسع في الخطوة 1.2 أو 1.3 إحباط المكالمة ، لكن الخطأ ليس قاتلاً - تستمر معالجة الدُفعات.
    • يتم تغيير مهام المرحلة الثانية قليلاً
      • يتم اكتشاف أي إعادة توجيه غير مؤكدة حديثًا لم يتم اكتشافها في الجولة الأولى من المرحلة 2 ، ولكن تتم إزالتها (بما في ذلك اسم الملف) دون إجراء إعادة التوجيه فعليًا
      • تتم إزالة أي مركب غير مؤلف من ذلك غير مصنف حديثًا في نهاية الخط دون إجراء استمرار في الخط
      • يتم إحباط المكالمة دون خطأ إذا تم اكتشاف أي مما يلي
        • الظهور حديثًا غير مؤلف ، دون تكييف & أو |
        • يبدأ رمز الأمر الناتج مع غير مسبوق ، دون تصنيف (
        • الرمز المميز الأول بعد بدء المكالمة التي تمت إزالتها بـ @
      • إذا كان الأمر الناتج صحيحًا على ما يبدو إذا أو لـ FOR ، فسيخفق التنفيذ لاحقًا مع خطأ في ذكر ذلك IF أو FOR غير معترف به كأمر داخلي أو خارجي.
      • بالطبع لا يتم إحباط المكالمة في هذه الجولة الثانية من المرحلة 2 إذا كان رمز الأمر الناتج عبارة :.
  • إذا تم استدعاء رمز الأمر الناتج ، فقم بإعادة تشغيل المرحلة 6 (يتكرر حتى لا يوجد مكالمة أخرى)
  • إذا كان رمز الأمر الناتج هو برنامج نصي دفعي أو: تسمية ، فإن تنفيذ المكالمة يتم التعامل معه بالكامل من خلال الباقي من المرحلة 6.
    • ادفع موضع ملف البرنامج النصي الحالي على مكدس الاتصال بحيث يمكن للتنفيذ استئناف من الموضع الصحيح عند اكتمال المكالمة.
    • قم بإعداد ٪ 0 ، ٪ 1 ، ٪ 2 ، ... ٪ n و ٪* رموز الوسيطة للمكالمة ، باستخدام جميع الرموز الناتجة
    • إذا كان رمز الأوامر عبارة عن تسمية تبدأ بـ :, ، ومن بعد
      • إعادة تشغيل المرحلة 5. هذا يمكن أن يؤثر على ما: التسمية تسمى. ولكن نظرًا لأن النسبة المئوية 0 وما إلى ذلك ، فقد تم إعداد الرموز المميزة بالفعل ، فإنها لن تغير الحجج التي يتم تمريرها إلى الروتين المسمى.
      • قم بتنفيذ علامة GOTO لوضع مؤشر الملف في بداية الروتين الفرعي (تجاهل أي رموز أخرى قد تتبع: التسمية) انظر المرحلة 7 للحصول على قواعد حول كيفية عمل GOTO.
    • آخر التحكم في نقل إلى البرنامج النصي الدُفعات المحدد.
    • يستمر تنفيذ "الاتصال": التسمية أو البرنامج النصي حتى يتم الوصول إلى الخروج /ب أو نهاية الملف ، وعند هذه النقطة يتم ظهر مكدس الاتصال ويستأنف التنفيذ من موضع الملف المحفوظ.
      لم يتم تنفيذ المرحلة 7 للبرامج النصية المسمى أو: الملصقات.
  • وإلا فإن نتيجة المرحلة 6 تنخفض حتى المرحلة 7 للتنفيذ.

المرحلة 7) التنفيذ: يتم تنفيذ الأمر

  • 7.1 - تنفيذ الأمر الداخلي - إذا تم اقتباس رمز الأوامر ، فقم بتخطي هذه الخطوة. خلاف ذلك ، حاول تحليل أمر داخلي وتنفيذ.
    • يتم إجراء الاختبارات التالية لتحديد ما إذا كان رمز الأوامر غير المخصصة يمثل أمرًا داخليًا:
      • إذا كان الرمز المميز للأمر يطابق أمرًا داخليًا تمامًا ، فعليك تنفيذه.
      • آخر كسر الرمز المميز للأمر قبل الحدوث الأول + / [ ] <space> <tab> , ; أو =
        إذا كان النص السابق أمرًا داخليًا ، فتذكر هذا الأمر
        • إذا كان في وضع سطر الأوامر ، أو إذا كان الأمر من كتلة أقواس ، إذا كان صحيحًا أو كتلة أمرًا صحيحًا ، في كتلة الأمر ، أو المشاركة في تسلس الأوامر ، قم بتنفيذ الأمر الداخلي
        • آخر (يجب أن يكون أمرًا مستقلًا في وضع الدُفعات) ، قم بفحص المجلد الحالي والمسار لـ .com ،
          • إذا كان ملف المطابقة الأول هو .bat أو .cmd ، فإن Goto 7.3.exec وقم بتنفيذ هذا البرنامج النصي
          • آخر (لم يتم العثور على المباراة أو المباراة الأولى هي .exe أو .com) تنفيذ الأمر الداخلي المتذكر
      • آخر كسر الرمز المميز للأمر قبل الحدوث الأول . \ أو :
        إذا لم يكن النص السابق أمرًا داخليًا ، فعندئذ GOTO 7.2
        وإلا فإن النص السابق قد يكون أمرًا داخليًا. تذكر هذا الأمر.
      • كسر الرمز المميز قبل الحدوث الأول + / [ ] <space> <tab> , ; أو =
        إذا كان النص السابق طريقًا إلى ملف موجود ، فإن Goto 7.2
        آخر تنفيذ الأمر الداخلي المتذكر.
    • إذا تم تحليل أمر داخلي من رمز أوامر أكبر ، يتم تضمين الجزء غير المستخدم من رمز الأوامر في قائمة الوسيطة
    • فقط لأن رمز الأوامر يتم تحليله كأمر داخلي لا يعني أنه سيتم تنفيذها بنجاح. كل أمر داخلي له قواعده الخاصة حول كيفية تحليل الحجج والخيارات ، وما هي بناء الجملة المسموح بها.
    • ستطبع جميع الأوامر الداخلية المساعدة بدلاً من أداء وظيفتها إذا /? تم الكشف عن. معظمهم يعترفون /? إذا ظهر في أي مكان في الحجج. ولكن هناك عدد قليل من الأوامر مثل Echo وتعيين مساعدة الطباعة فقط إذا بدأ رمز الوسيطة الأولى بـ /?.
    • SET لديها بعض الدلالات المثيرة للاهتمام:
      • إذا كان أمر SET يحتوي على اقتباس قبل تمكين الاسم المتغير وتمكين الإضافات
        set "name=content" ignored --> القيمة =content
        ثم يتم استخدام النص بين العلامة المتساوية الأولى والاقتباس الأخير كمحتوى (يساوي الأول والاقتباس الأخير). يتم تجاهل النص بعد الاقتباس الأخير. إذا لم يكن هناك اقتباس بعد العلامة المتساوية ، فسيتم استخدام بقية الخط كمحتوى.
      • إذا لم يكن لأمر مجموعة اقتباس قبل الاسم
        set name="content" not ignored --> القيمة ="content" not ignored
        ثم يتم استخدام الباقي بأكمله من السطر بعد المساواة كمحتوى ، بما في ذلك أي وجميع الاقتباسات التي قد تكون موجودة.
    • يتم تقييم المقارنة إذا كانت الحالة صحيحة أو خاطئة ، تتم معالجة كتلة الأوامر المعتمدة بالفعل المحسورة بالفعل ، بدءًا من المرحلة 5.
    • يتم تكرار شرط in a for command بشكل مناسب.
      • إذا كان هذا هو لـ /f يكرر إخراج كتلة الأوامر ، ثم:
        • يتم تنفيذ البند في عملية cmd.exe جديدة عبر cmd /c.
        • يجب أن تمر كتلة الأوامر من خلال عملية التحليل بأكملها للمرة الثانية ، ولكن هذه المرة في سياق سطر الأوامر
        • سيبدأ ECHO ، وسيبدأ التوسع المتأخر عادةً معاقًا (يعتمد على إعداد السجل)
        • سيتم فقد جميع التغييرات في البيئة التي أجراها كتلة Command Command بمجرد أن تنتهي عملية CMD.exe الطفل
      • لكل تكرار:
        • يتم تعريف القيم المتغيرة
        • ثم تتم معالجة كتلة القيادة التي تم تحليلها بالفعل ، بدءًا من المرحلة 4.
    • يستخدم Goto المنطق التالي لتحديد موقع: التسمية
      • تم تحليل التسمية من رمز الوسيطة الأولى
      • يتم فحص البرنامج النصي لحدوث الملصق التالي
        • يبدأ المسح من موضع الملف الحالي
        • إذا تم الوصول إلى نهاية الملف ، فسيحلق المسح الضوئي مرة أخرى إلى بداية الملف وتستمر في نقطة البداية الأصلية.
      • يتوقف المسح عند الحدوث الأول للتسمية التي يجدها ، ويتم ضبط مؤشر الملف على السطر مباشرة بعد التسمية. تنفيذ السيناريو يستأنف من تلك النقطة. لاحظ أن GOTO الحقيقي الناجح سيؤدي على الفور إلى إحباط أي كتلة من الكود المتوفرة ، بما في ذلك الحلقات.
      • إذا لم يتم العثور على التسمية ، أو مفقودة الرمز المميز ، فإن GOTO تفشل ، يتم طباعة رسالة خطأ ، ويتم عرض مكدس الاتصال. يعمل هذا بشكل فعال كخروج /ب ، باستثناء أي أوامر محسورة بالفعل في كتلة الأوامر الحالية التي تتبع GOTO لا يزال يتم تنفيذها ، ولكن في سياق المتصل (السياق الموجود بعد الخروج /ب)
      • نرى https://www.dostips.com/forum/viewtopic.php؟f=3&t=3803 للحصول على وصف أكثر دقة للقواعد المستخدمة في تحليل الملصقات.
    • إعادة تسمية ونسخ كلاهما يقبلون البطاقات البرية للمسارات المصدر والهدف. لكن Microsoft تقوم بعمل فظيع لتوثيق كيفية عمل البطاقات البرية ، خاصة بالنسبة للمسار المستهدف. يمكن العثور على مجموعة مفيدة من قواعد البطاقة البرية في كيف يقوم الأمر بإعادة تسمية نظام Windows بتفسير الأحرف البرية؟
  • 7.2 - تنفيذ تغيير مستوى الصوت - وإلا إذا لم يبدأ رمز الرمز المميز باقتباس ، فقد كان طول حرفين بالضبط ، والشخصية الثانية هي قولون ، ثم قم بتغيير الحجم
    • يتم تجاهل جميع رموز الحجة
    • إذا كان لا يمكن العثور على وحدة التخزين المحددة بواسطة الحرف الأول ، فقم بإهانة مع خطأ
    • رمز أمر من :: سيؤدي دائمًا إلى خطأ ما لم يتم استخدام STECT لتحديد مستوى الصوت ::
      إذا تم استخدام STEMN لتحديد وحدة التخزين ::, ، ثم سيتم تغيير مستوى الصوت ، ولن يتم التعامل معها كتسمية.
  • 7.3 - تنفيذ الأمر الخارجي - حاول التعامل مع الأمر كأمر خارجي.
    • إذا لم يتم اقتباس وضع سطر الأوامر ولا يبدأ بمواصفات وحدة التخزين ، فاكسر رمز الرمز المميز عند الحدوث الأول <space> , ; أو = وقم بتعبئة الباقي إلى رمز (ق) الحجة.
    • إذا كان الحرف الثاني لرمز الأوامر هو القولون ، فاحقق من الحجم المحدد بواسطة الحرف الأول.
      إذا كان لا يمكن العثور على مستوى الصوت ، فقم بإهانة مع خطأ.
    • إذا كان في وضع الدُفعات ويبدأ رمز الأوامر بـ :, ، ثم غوتو 7.4
      لاحظ أنه إذا بدأ رمز التسمية بـ ::, ، لن يتم الوصول إلى هذا لأن الخطوة السابقة قد تم إحباطها مع خطأ ما لم يتم استخدام STECT لتحديد وحدة التخزين ::.
    • تحديد الأمر الخارجي للتنفيذ.
      • هذه عملية معقدة قد تتضمن مستوى الصوت الحالي أو الدليل الحالي أو متغير المسار أو متغير PathExt و / أو جمعيات الملفات.
      • إذا كان لا يمكن تحديد أمر خارجي صالح ، فإذا أدى إلى إحباط خطأ.
    • إذا كان في وضع سطر الأوامر ويبدأ رمز الأوامر بـ :, ، ثم غوتو 7.4
      لاحظ أن هذا نادراً ::, ويستخدم Subst لتحديد وحدة التخزين ::, ، ورمز الأوامر بأكمله هو مسار صالح لأمر خارجي.
    • 7.3.exec - تنفيذ الأمر الخارجي.
  • 7.4 - تجاهل التسمية - تجاهل الأمر وجميع وسائطه إذا بدأ رمز الأمر بـ :.
    القواعد في 7.2 و 7.3 قد تمنع الملصق من الوصول إلى هذه النقطة.

محلل سطر الأوامر:

يعمل مثل Batchline-Parser ، باستثناء:

المرحلة 1) التوسع في المئة:

  • رقم %*, %1 الخ. توسع الحجة
  • إذا كان var غير محدد ، إذن %var% ترك دون تغيير.
  • لا معالجة خاصة ل %%. إذا var = المحتوى ، ثم %%var%% يتوسع إلى %content%.

المرحلة 3) صدى الأوامر (الأوامر) المتوفرة

  • لا يتم تنفيذ هذا بعد المرحلة 2. يتم تنفيذها فقط بعد المرحلة 4 لكتلة أمر DO.

المرحلة 5) التوسع المتأخر: فقط إذا تم تمكين التأخير

  • إذا كان var غير محدد ، إذن !var! ترك دون تغيير.

المرحلة 7) تنفيذ الأمر

  • محاولات الاتصال أو GOTO A: تسمية تؤدي إلى خطأ.
  • كما تم توثيقه بالفعل في المرحلة 7 ، قد تؤدي التسمية المنفذة إلى خطأ في ظل سيناريوهات مختلفة.
    • لا يمكن أن تتسبب الملصقات التي تم تنفيذها في الدُفعات إلا إذا بدأت ::
    • تسميات سطر الأوامر التي تم تنفيذها تؤدي دائمًا إلى خطأ

تحليل قيم عدد صحيح

هناك العديد من السياقات المختلفة حيث تقوم cmd.exe بتوصيف القيم العددية من الأوتار ، والقواعد غير متسقة:

  • SET /A
  • IF
  • %var:~n,m% (توسيع فرعي متغير)
  • FOR /F "TOKENS=n"
  • FOR /F "SKIP=n"
  • FOR /L %%A in (n1 n2 n3)
  • EXIT [/B] n

يمكن العثور على تفاصيل هذه القواعد في قواعد لكيفية توزيل cmd.exe الأرقام


لأي شخص يرغب في تحسين قواعد التحليل cmd.exe ، هناك أ موضوع المناقشة في منتدى Dostips حيث يمكن الإبلاغ عن المشكلات وتقديم الاقتراحات.

أتمنى أن يساعد ذلك
جان إريك (JEB) - المؤلف الأصلي واكتشاف المراحل
ديف بنهام (DBENHAM) - الكثير من المحتوى والتحرير

نصائح أخرى

عند استدعاء أمر من نافذة أمر ، لم يتم إجراء رمز لوسائط سطر الأوامر بواسطة cmd.exe (الملقب "القذيفة"). غالبًا ما يتم إجراء الرمز المميز عن طريق تشغيل C/C ++ للعمليات التي تم تشكيلها حديثًا ، ولكن هذا ليس بالضرورة - على سبيل المثال ، إذا لم يتم كتابة العملية الجديدة في C/C ++ ، أو إذا اختارت العملية الجديدة تجاهلها argv ومعالجة خط الأوامر الخام لنفسه (على سبيل المثال مع getCommandline ()). على مستوى نظام التشغيل ، تمر Windows Lines غير المحسوسة كسلسلة واحدة لعمليات جديدة. هذا على النقيض من معظم قذائف *nix ، حيث تقوم قذيفة رمز الحجج بطريقة متسقة يمكن التنبؤ بها قبل نقلها إلى العملية التي تم تشكيلها حديثًا. كل هذا يعني أنك قد تواجه سلوكًا متباينًا في رمز الرمز المميز عبر برامج مختلفة على Windows ، حيث غالبًا ما تأخذ البرامج الفردية الرمز المميز في أيديهم.

إذا بدا الأمر وكأنه فوضى ، فهذا نوع من. ومع ذلك ، منذ عدد كبير من برامج Windows فعل استخدم وقت تشغيل Microsoft C/C ++ argv, ، قد يكون من المفيد بشكل عام الفهم كيف تميز MSVCRT الحجج. هنا مقتطفات:

  • يتم تحديد الحجج بواسطة الفضاء الأبيض ، وهو إما مساحة أو علامة تبويب.
  • يتم تفسير سلسلة محاطة بعلامات اقتباس مزدوجة كحجة واحدة ، بغض النظر عن المساحة البيضاء الموجودة في الداخل. يمكن تضمين سلسلة مقتبسة في حجة. لاحظ أنه لم يتم التعرف على Caret (^) كحرف هروب أو محدد.
  • يتم تفسير علامة اقتباس مزدوجة مسبوقة بخلع خلفي ، "، على أنها علامة اقتباس مزدوجة حرفية (").
  • يتم تفسير الانزلاقات الخلفية حرفيًا ، ما لم تسبق على الفور علامة اقتباس مزدوجة.
  • إذا تم اتباع عدد زوجي من التراجع الخلفي بعلامة اقتباس مزدوجة ، فسيتم وضع واحد عكسي () في صفيف ArgV لكل زوج من الذرات الخلفية () ، ويتم تفسير علامة الاقتباس المزدوجة (") على أنها حلقة سلسلة.
  • إذا تم اتباع عدد فردي من عمليات الرفع الخلفي بعلامة اقتباس مزدوجة ، فسيتم وضع واحد عكسي () في صفيف ArgV لكل زوج من الذرات الخلفية () ويتم تفسير علامة الاقتباس المزدوجة على أنها تسلسل هروب من قبل الملاط المتبقي ، مما يسبب علامة اقتباس مزدوجة حرفية (") ليتم وضعها في Argv.

Microsoft "لغة الدُفعات" (.bat) ليس استثناءً من هذه البيئة الفوضوية ، وقد طورت قواعدها الفريدة الخاصة بها للرمز والهروب. يبدو أيضًا أن موجه الأوامر الخاص بـ cmd.exe يقوم ببعض المعالجة المسبقة لحجة سطر الأوامر (معظمها للحصول على استبدال متغير والهروب) قبل نقل الوسيطة إلى العملية المنفذة حديثًا. يمكنك قراءة المزيد حول التفاصيل ذات المستوى المنخفض للغة الدُفعات وتهرب CMD في الإجابات الممتازة التي كتبها Jeb و Dbenham في هذه الصفحة.


دعنا نبني أداة سطر أوامر بسيطة في C ونرى ما تقوله حول حالات الاختبار الخاصة بك:

int main(int argc, char* argv[]) {
    int i;
    for (i = 0; i < argc; i++) {
        printf("argv[%d][%s]\n", i, argv[i]);
    }
    return 0;
}

(ملاحظات: Argv [0] هو دائمًا اسم القابل للتنفيذ ، ويتم حذفه أدناه للإيجاز. تم اختباره على نظام التشغيل Windows XP SP3. تم تجميعه مع Visual Studio 2005.)

> test.exe "a ""b"" c"
argv[1][a "b" c]

> test.exe """a b c"""
argv[1]["a b c"]

> test.exe "a"" b c
argv[1][a" b c]

وبعض اختباراتي الخاصة:

> test.exe a "b" c
argv[1][a]
argv[2][b]
argv[3][c]

> test.exe a "b c" "d e
argv[1][a]
argv[2][b c]
argv[3][d e]

> test.exe a \"b\" c
argv[1][a]
argv[2]["b"]
argv[3][c]

قواعد التوسع في المئة

هنا شرح موسع للمرحلة 1 في إجابة جيب (صالح لكل من وضع الدُفعات ووضع سطر الأوامر).

المرحلة 1) التوسع في المئةبدءًا من اليسار ، قم بمسح كل حرف % أو <LF>. إذا وجدت بعد ذلك

  • 1.05 (الخط المقطوع في <LF>)
    • إذا كانت الشخصية <LF> ومن بعد
      • إسقاط (تجاهل) ما تبقى من الخط من <LF> فصاعدا
      • Goto Phase 1.5 (الشريط <CR>)
    • وإلا يجب أن تكون الشخصية %, ، لذا انتقل إلى 1.1
  • 1.1 (الهروب %) تخطي لو وضع سطر الأوامر
    • إذا وضع الدُفعة وتتبعه آخر % ومن بعد
      يحل محل %% مع واحد % ومتابعة المسح
  • 1.2 (توسيع الحجة) تخطي لو وضع سطر الأوامر
    • آخر إذا وضع الدُفعة ثم
      • إذا تليها * ويتم تمكين امتدادات الأوامر بعد ذلك
        يحل محل %* مع نص كل وسيط سطر الأوامر (استبدل لا شيء إذا لم تكن هناك وسيط) واستمر في المسح.
      • آخر إذا تبعه <digit> ومن بعد
        يحل محل %<digit> مع قيمة الوسيطة (استبدل لا شيء إذا كان غير محدد) واستمر في المسح.
      • آخر إذا تبعه ~ ويتم تمكين امتدادات الأوامر بعد ذلك
        • إذا تليها قائمة صالحة اختيارية لمعدلات الوسيطة تليها المطلوبة <digit> ومن بعد
          يحل محل %~[modifiers]<digit> مع قيمة الوسيطة المعدلة (استبدل لا شيء إذا لم يتم تحديده أو إذا تم تحديده مسار $ المحدد: لم يتم تعريف المعدل) ومتابعة المسح.
          ملاحظة: المعدلات غير حساسة للحالة ويمكن أن تظهر عدة مرات بأي ترتيب ، باستثناء المسار $: يمكن أن يظهر المعدل مرة واحدة فقط ويجب أن يكون المعدل الأخير قبل <digit>
        • آخر بناء جملة الوسيطة المعدلة غير صالحة خطأ فادح: يتم إحباط جميع الأوامر المحسورة ، وإحباط معالجة الدُفعات إذا كان في وضع الدُفعات!
  • 1.3 (توسيع المتغير)
    • آخر إذا تم تعطيل ملحقات الأوامر بعد ذلك
      انظر إلى السلسلة التالية من الأحرف ، كسر من قبل % أو نهاية المخزن المؤقت ، ودعوها var (قد تكون قائمة فارغة)
      • إذا كانت الشخصية التالية % ومن بعد
        • إذا تم تعريف var ثم
          يحل محل %VAR% مع قيمة VAR ومتابعة المسح
        • آخر إذا وضع الدُفعة ثم
          إزالة %VAR% ومتابعة المسح
        • آخر Goto 1.4
      • آخر Goto 1.4
    • آخر إذا تم تمكين امتدادات الأوامر بعد ذلك
      انظر إلى السلسلة التالية من الأحرف ، كسر من قبل % : أو نهاية المخزن المؤقت ، ودعوها var (قد تكون قائمة فارغة). إذا كسر فار من قبل : والشخصية اللاحقة % ثم تشمل : كحرف آخر في فار وكسر من قبل %.
      • إذا كانت الشخصية التالية % ومن بعد
        • إذا تم تعريف var ثم
          يحل محل %VAR% مع قيمة VAR ومتابعة المسح
        • آخر إذا وضع الدُفعة ثم
          إزالة %VAR% ومتابعة المسح
        • آخر Goto 1.4
      • آخر إذا كانت الشخصية التالية : ومن بعد
        • إذا كان VAR غير محدد بعد ذلك
          • إذا وضع الدُفعة ثم
            إزالة %VAR: ومتابعة المسح.
          • آخر Goto 1.4
        • آخر إذا كانت الشخصية التالية ~ ومن بعد
          • إذا كانت السلسلة التالية من الأحرف تطابق نمط [integer][,[integer]]% ومن بعد
            يحل محل %VAR:~[integer][,[integer]]% مع فرقة قيمة VAR (ربما تؤدي إلى سلسلة فارغة) ومتابعة المسح.
          • آخر Goto 1.4
        • آخر إذا تبعه = أو *= ومن بعد
          البحث المتغير غير صالح واستبدال بناء الجملة خطأ فادح: يتم إحباط جميع الأوامر المحسورة ، وإحباط معالجة الدُفعات إذا كان في وضع الدُفعات!
        • آخر إذا كانت السلسلة التالية من الأحرف تطابق نمط [*]search=[replace]%, ، حيث قد يتضمن البحث أي مجموعة من الأحرف باستثناء =, و reply قد يتضمن أي مجموعة من الأحرف باستثناء %, ، ثم استبدل
          %VAR:[*]search=[replace]% مع قيمة var بعد إجراء البحث واستبداله (ربما يؤدي إلى سلسلة فارغة) ومتابعة المسح الضوئي
        • آخر Goto 1.4
  • 1.4 (قطاع ٪)
    • آخر إذا وضع الدُفعة ثم
      إزالة % واستمر في الفحص بدءًا من الحرف التالي بعد %
    • آخر الحفاظ %واستمر في الفحص بدءًا من الحرف التالي بعد %

ما سبق يساعد في شرح سبب هذه الدفعة

@echo off
setlocal enableDelayedExpansion
set "1var=varA"
set "~f1var=varB"
call :test "arg1"
exit /b  
::
:test "arg1"
echo %%1var%% = %1var%
echo ^^^!1var^^^! = !1var!
echo --------
echo %%~f1var%% = %~f1var%
echo ^^^!~f1var^^^! = !~f1var!
exit /b

يعطي هذه النتائج:

%1var% = "arg1"var
!1var! = varA
--------
%~f1var% = P:\arg1var
!~f1var! = varB

ملاحظة 1 - تحدث المرحلة الأولى قبل التعرف على بيانات REM. هذا أمر مهم للغاية لأنه يعني أن الملاحظة يمكن أن تولد خطأً قاتلًا إذا كان لديه بناء جملة توسع الوسيطة غير صالح أو بحث متغير غير صالح واستبدال بناء الجملة!

@echo off
rem %~x This generates a fatal argument expansion error
echo this line is never reached

ملاحظة 2 - نتيجة أخرى مثيرة للاهتمام لقواعد التحليل ٪: المتغيرات التي تحتوي على: في الاسم يمكن تعريفها ، ولكن لا يمكن توسيعها ما لم يتم تعطيل ملحقات الأوامر. هناك استثناء واحد - يمكن توسيع اسم متغير يحتوي على قولون واحد في النهاية أثناء تمكين امتدادات الأوامر. ومع ذلك ، لا يمكنك تنفيذ عمليات التسجيل أو البحث واستبدال العمليات على أسماء متغيرة تنتهي مع القولون. يوضح ملف الدُفعات أدناه (بإذن من JEB) هذا السلوك

@echo off
setlocal
set var=content
set var:=Special
set var::=double colon
set var:~0,2=tricky
set var::~0,2=unfortunate
echo %var%
echo %var:%
echo %var::%
echo %var:~0,2%
echo %var::~0,2%
echo Now with DisableExtensions
setlocal DisableExtensions
echo %var%
echo %var:%
echo %var::%
echo %var:~0,2%
echo %var::~0,2%

ملاحظة 3 - نتيجة مثيرة للاهتمام لترتيب قواعد التحليل التي يضعها Jeb في منشوره: عند أداء البحث والاستبدال بالتأخير ، يجب الهروب أو الإقالة لكن الموقف يختلف عن التوسع في المئة - يجب عدم الهروب من مصطلح البحث (على الرغم من أنه يمكن نقله). قد تتطلب أو لا تتطلب السلسلة المئوية لـ Escape Escape أو اقتباس ، اعتمادًا على نيتك.

@echo off
setlocal enableDelayedExpansion
set "var=this & that"
echo %var:&=and%
echo "%var:&=and%"
echo !var:^&=and!
echo "!var:&=and!"

تأخير قواعد التوسع

فيما يلي شرح موسع وأكثر دقة للمرحلة 5 في إجابة جيب (صالح لكل من وضع الدُفعات ووضع سطر الأوامر)

المرحلة 5) تأخر التوسع

يتم تخطي هذه المرحلة في حالة تطبيق أي من الشروط التالية:

  • تم تعطيل التوسع المتأخر.
  • يكون الأمر ضمن كتلة أقواس على جانبي الأنبوب.
  • رمز الأوامر الواردة هو نص دفع "عاري" ، مما يعني أنه غير مرتبط به CALL, ، كتلة أقواس ، أي شكل من أشكال تسلسل الأوامر (&, && أو ||) ، أو أنبوب |.

يتم تطبيق عملية التوسع المتأخرة على الرموز بشكل مستقل. قد يكون للأمر رموز متعددة:

  • الرمز المميز. بالنسبة لمعظم الأوامر اسم الأمر نفسه هو رمز. لكن هناك بعض الأوامر لها مناطق متخصصة تعتبر رمزًا للمرحلة 5.
    • for ... in(TOKEN) do
    • if defined TOKEN
    • if exists TOKEN
    • if errorlevel TOKEN
    • if cmdextversion TOKEN
    • if TOKEN comparison TOKEN, ، حيث المقارنة هي واحدة من ==, equ, neq, lss, leq, gtr, ، أو geq
  • الرمز المميز للحجج
  • الرمز المميز للوجهة لإعادة التوجيه (واحد لكل توجيه)

لا يوجد تغيير على الرموز التي لا تحتوي !.

لكل رمز يحتوي على واحد على الأقل !, ، مسح كل حرف من اليسار إلى اليمين من أجل ^ أو !, ، وإذا وجدت ، إذن

  • 5.1 (Caret Escape) اللازمة ل ! أو ^ الحرفية
    • إذا كانت الشخصية هياريت ^ ومن بعد
      • مسح ال ^
      • مسح الشخصية التالية والحفاظ عليها كحرفي
      • تابع المسح
  • 5.2 (توسيع المتغير)
    • إذا كانت الشخصية !, ، ومن بعد
      • إذا تم تعطيل ملحقات الأوامر ثم
        انظر إلى السلسلة التالية من الأحرف ، كسر من قبل ! أو <LF>, ، ودعهم var (قد تكون قائمة فارغة)
        • إذا كانت الشخصية التالية ! ومن بعد
          • إذا تم تعريف var ، إذن
            يحل محل !VAR! مع قيمة VAR ومتابعة المسح
          • آخر إذا وضع الدُفعة ثم
            إزالة !VAR! ومتابعة المسح
          • آخر Goto 5.2.1
        • آخر Goto 5.2.1
      • آخر إذا تم تمكين امتدادات الأوامر بعد ذلك
        انظر إلى السلسلة التالية من الأحرف ، كسر من قبل !, :, ، أو <LF>, ، ودعوهم var (قد تكون قائمة فارغة). إذا كسر فار من قبل : والشخصية اللاحقة ! ثم تشمل : كحرف آخر في فار وكسر من قبل !
        • إذا كانت الشخصية التالية ! ومن بعد
          • إذا كان var موجود ، إذن
            يحل محل !VAR! مع قيمة VAR ومتابعة المسح
          • آخر إذا وضع الدُفعة ثم
            إزالة !VAR! ومتابعة المسح
          • آخر Goto 5.2.1
        • آخر إذا كانت الشخصية التالية : ومن بعد
          • إذا كان VAR غير محدد بعد ذلك
            • إذا وضع الدُفعة ثم
              إزالة !VAR: ومتابعة المسح
            • آخر Goto 5.2.1
          • آخر إذا كانت السلسلة التالية من الأحرف تطابق نمط
            ~[integer][,[integer]]! ومن بعد
            يحل محل !VAR:~[integer][,[integer]]! مع فرقة قيمة VAR (ربما تؤدي إلى سلسلة فارغة) ومتابعة المسح الضوئي
          • آخر إذا كانت السلسلة التالية من الأحرف تطابق نمط [*]search=[replace]!, ، حيث قد يتضمن البحث أي مجموعة من الأحرف باستثناء =, و reply قد يتضمن أي مجموعة من الأحرف باستثناء !, ، ومن بعد
            يحل محل !VAR:[*]search=[replace]! مع قيمة var بعد إجراء البحث واستبداله (ربما يؤدي إلى سلسلة فارغة) ومتابعة المسح الضوئي
          • آخر Goto 5.2.1
        • آخر Goto 5.2.1
      • 5.2.1
        • إذا وضع الدُفعة ثم قم بإزالة ملف !
          آخر الحفاظ على !
        • تابع الفحص بدءًا من الحرف التالي بعد !

كما هو موضح ، يتم تمرير الأوامر سلسلة الوسيطة بأكملها في μsoft Land ، ويعود الأمر إلى تحليل هذا إلى وسيطات منفصلة لاستخدامها الخاص. لا يوجد أي تناسق في هذا بين البرامج المختلفة ، وبالتالي لا توجد مجموعة من القواعد لوصف هذه العملية. تحتاج حقًا إلى التحقق من كل حالة زاوية لأي مكتبة C التي يستخدمها البرنامج.

بقدر النظام .bat الملفات تذهب ، هنا هذا الاختبار:

c> type args.cmd
@echo off
echo cmdcmdline:[%cmdcmdline%]
echo 0:[%0]
echo *:[%*]
set allargs=%*
if not defined allargs goto :eof
setlocal
@rem Wot about a nice for loop?
@rem Then we are in the land of delayedexpansion, !n!, call, etc.
@rem Plays havoc with args like %t%, a"b etc. ugh!
set n=1
:loop
    echo %n%:[%1]
    set /a n+=1
    shift
    set param=%1
    if defined param goto :loop
endlocal

الآن يمكننا إجراء بعض الاختبارات. معرفة ما إذا كان يمكنك معرفة ما تحاول μsoft القيام به:

C>args a b c
cmdcmdline:[cmd.exe ]
0:[args]
*:[a b c]
1:[a]
2:[b]
3:[c]

بخير حتى الآن. (سأترك غير مهتم %cmdcmdline% و %0 من الان فصاعدا.)

C>args *.*
*:[*.*]
1:[*.*]

لا توسع اسم الملف.

C>args "a b" c
*:["a b" c]
1:["a b"]
2:[c]

لا اقتباس تجريد ، على الرغم من أن الاقتباسات تمنع تقسيم الحجة.

c>args ""a b" c
*:[""a b" c]
1:[""a]
2:[b" c]

الاقتباسات المزدوجة المتتالية تجعلهم يخسرون أي قدرات تحليلية خاصة قد يكون لديهم. مثال @بينو:

C>args "a """ b "" c"""
*:["a """ b "" c"""]
1:["a """]
2:[b]
3:[""]
4:[c"""]

مسابقة: كيف تمر بقيمة أي بيئة var كملف غير مرتبطة الحجة (أي ، كما %1) إلى ملف الخفافيش؟

c>set t=a "b c
c>set t
t=a "b c
c>args %t%
1:[a]
2:["b c]
c>args "%t%"
1:["a "b]
2:[c"]
c>Aaaaaargh!

يبدو التحليل العاقل مكسورة إلى الأبد.

للترفيه الخاص بك ، حاول إضافة متنوعة ^, \, ', & (& c.) الشخصيات لهذه الأمثلة.

لديك بعض الإجابات الرائعة أعلاه بالفعل ، ولكن للإجابة على جزء واحد من سؤالك:

set a =b, echo %a %b% c% → bb c%

ما يحدث هناك هو أن لديك مساحة قبل = ، يتم إنشاء متغير يسمى %a<space>%لذلك عندما أنت echo %a % يتم تقييم ذلك بشكل صحيح كما b.

الجزء المتبقي b% c% ثم يتم تقييمه كنص عادي + متغير غير محدد % c%, ، والتي يجب أن تتردد كما كتبت ، بالنسبة لي echo %a %b% c% عائدات bb% c%

أظن أن القدرة على تضمين المساحات في أسماء متغيرة هي أكثر من الإشراف من "ميزة" المخطط لها

تحرير: انظر الإجابة المقبولة ، ما يلي خطأ ويشرح فقط كيفية تمرير سطر الأوامر إلى Tinyperl.


فيما يتعلق بالاقتباسات ، لدي شعور بأن السلوك هو ما يلي:

  • عندما " تم العثور عليه ، يبدأ التسلل سلسلة
  • عندما يحدث الولادة:
    • كل شخصية ليست ملف " هو globbed
    • عندما " وجد:
      • إذا تم اتباعه "" (وبالتالي ثلاثية ") ثم يتم إضافة اقتباس مزدوج إلى السلسلة
      • إذا تم اتباعه " (وبالتالي مزدوج ") ثم يتم إضافة اقتباس مزدوج إلى السلسلة ونهايات التسلسل
      • إذا لم تكن الشخصية التالية ", ، نهايات التسلسل
    • عندما ينتهي الخط ، ينتهي التسلسل.

بالمختصر:

"a """ b "" c""" يتكون من سلسلتين: a " b " و c"

"a"", "a""" و"a"""" كلها نفس السلسلة إذا في نهاية الخط

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top