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" מגיע כמחרוזת אחת), וה-shell מרחיב תבניות כמו *.txt לשמות קבצים עוד לפני ש-Node.js רואה אותן.

לקבל את הארגומנטים עם slice(2)

רוב הסקריפטים עושים destructuring לארגומנטים שהם מצפים להם ונותנים לכל אחד ערך ברירת מחדל:

הוא הדפיס Hello, Ada: ארגומנט אחד מילא את name, ו-greeting חזר לערך ברירת המחדל שלו. הוסיפו Hi אחרי Ada בשורת הארגומנטים והוא ידפיס Hi, Ada; רוקנו את השורה ותקבלו Hello, world.

מספרים מגיעים כמחרוזות

ל-shell אין טיפוסים. כל ארגומנט הוא מחרוזת, כך שחשבון עליהם יוצא שגוי עד שממירים אותם:

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, כי מחרוזות מושוות תו אחרי תו. המירו קודם.

לשים סודות בארגומנטים. שורות פקודה מופיעות בהיסטוריה של ה-shell וברשימות תהליכים שמשתמשים אחרים במחשב יכולים לקרוא. העבירו סיסמאות ומפתחות 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

להתחיל