Menu

process.argv في Node.js: قراءة وسائط سطر الأوامر

process.argv مصفوفة بسطر الأوامر الذي شغّل برنامجك: الملف التنفيذي node، ثم مسار السكربت، ثم كل وسيط كتبته. استخدم process.argv.slice(2) لتحصل على وسائطك فقط.

تحتوي هذه الصفحة على محررات قابلة للتشغيل. حرّر، شغّل، وشاهد النتيجة فوراً.

process.argv مصفوفة تحمل سطر الأوامر الذي شغّل برنامج Node.js. الفهرس 0 هو مسار الملف التنفيذي node، والفهرس 1 هو مسار سكربتك، ووسائطك أنت تبدأ من الفهرس 2. إذن يعطيك process.argv.slice(2) بالضبط ما كتبه المستخدم بعد اسم الملف، ودائمًا كنصوص.

العنصران الأولان مساران كاملان، لذلك لا يطبع المثال إلا الجزء الأخير من كل منهما (node وindex.js)، ثم [ 'Ada', '42', '--verbose' ]. عدّل صف الوسائط إلى Grace 7 وشغّل من جديد: تتغير المصفوفة معه.

ما الذي يدخل في process.argv

تقسم الصدفة (shell) السطر الواقع بعد node عند المسافات وتسلّم القطع إلى Node.js. الخيارات المكتوبة قبل اسم الملف تخص Node.js نفسه، لا برنامجك:

node --max-old-space-size=4096 index.js --port=8080
# process.argv.slice(2) is [ '--port=8080' ]
# process.execArgv is      [ '--max-old-space-size=4096' ]

علامات الاقتباس تجمع الكلمات في وسيط واحد ("Ada Lovelace" يصل كنص واحد)، وتوسّع الصدفة أنماطًا مثل *.txt إلى أسماء ملفات قبل أن يراها Node.js أصلًا.

احصل على الوسائط عبر slice(2)

تفكك معظم السكربتات الوسائط التي تتوقعها وتعطي كلًا منها قيمة افتراضية:

طبع Hello, Ada: ملأ وسيط واحد name، ورجع greeting إلى قيمته الافتراضية. أضف Hi بعد Ada في صف الوسائط فيطبع Hi, Ada؛ وأفرغ الصف فتحصل على Hello, world.

الأرقام تصل كنصوص

لا أنواع في الصدفة. كل وسيط نص، لذلك تخطئ العمليات الحسابية عليه حتى تحوّله:

ضمّ a + b النصين إلى 75، وأعطى Number() القيمة 12. الكلمة التي ليست رقمًا تصبح NaN، فتحقق بـ Number.isNaN واطبع رسالة استخدام بدلًا من المتابعة بقيمة معطوبة.

تحليل خيارات --name=value يدويًا

لخيارين أو ثلاثة تكفي حلقة قصيرة. هذه تحوّل --port=8080 إلى port: '8080'، و--verbose المجرد إلى true، وتحتفظ بكل ما عدا ذلك كوسيط موضعي:

طبع {"port":"8080","verbose":true} و[ 'build', 'src' ]، وما زالت port نصًا. لا تتعامل هذه الحلقة مع الخيارات القصيرة مثل -p ولا مع قيمة في الوسيط التالي (--port 8080)؛ لذلك استخدم المحلل المدمج أدناه.

util.parseArgs، المحلل المدمج

يأتي Node.js 18.3 وما بعده مع util.parseArgs، الذي يتعامل مع الخيارات الطويلة والقصيرة، والقيم في الوسيط التالي، والقيم المنطقية، والقيم الافتراضية:

const { parseArgs } = require('node:util');

// node index.js -p 8080 --verbose src
const { values, positionals } = parseArgs({
    options: {
        port: { type: 'string', short: 'p', default: '3000' },
        verbose: { type: 'boolean', short: 'v' },
    },
    allowPositionals: true,
});

console.log(values);      // [Object: null prototype] { port: '8080', verbose: true }
console.log(positionals); // [ 'src' ]

يقرأ parseArgs القيمة process.argv.slice(2) افتراضيًا. ويرمي خطأ عند خيار لم تعلن عنه، وهذا يلتقط الأخطاء الإملائية مثل --prot؛ مرّر strict: false لقبول الخيارات غير المعروفة. أنواع الخيارات هي string وboolean فقط، فما زالت الأرقام تحتاج Number(). وvalues كائن بلا prototype، ولهذا يُطبع مع [Object: null prototype]؛ اقرأه كأي كائن.

أخطاء شائعة

قراءة process.argv[0] على أنه الوسيط الأول. إنه مسار node. وسيطك الأول هو process.argv[2].

نسيان أن كل شيء نص. '10' > '9' قيمته false، لأن النصوص تُقارن حرفًا حرفًا. حوّل أولًا.

وضع الأسرار في الوسائط. تظهر أسطر الأوامر في سجل الصدفة وفي قوائم العمليات التي يستطيع المستخدمون الآخرون على الجهاز قراءتها. مرّر كلمات المرور ومفاتيح API عبر متغيرات البيئة بدلًا من ذلك.

الأسئلة الشائعة

كيف أمرر وسائط إلى سكربت npm؟

ضعها بعد --: npm run start -- --port=4000. يمرر npm كل ما يأتي بعد -- إلى سكربتك، فيظهر في process.argv.slice(2).

لماذا قيمة process.argv[2] هي undefined؟

لأن البرنامج شُغّل دون ذلك الوسيط. أعطه قيمة افتراضية (process.argv[2] ?? 'guest')، أو اطبع سطرًا يشرح طريقة الاستخدام وأوقف البرنامج بـ process.exit(1).

هل أستخدم yargs أو commander بدلًا من process.argv؟

لسكربت فيه بضعة خيارات، util.parseArgs مدمج ويكفي. تضيف حزم مثل commander وyargs نصوص المساعدة والأوامر الفرعية والتحقق من المدخلات، وهذا يستحق العناء حين تصبح لأداتك عدة أوامر.

رسم توضيحي للغات البرمجة في Coddy

تعلّم البرمجة مع Coddy

ابدأ الآن