如何将命令行参数传递给 Node.js 程序并接收它们?

How do I pass command line arguments to a Node.js program and receive them?

提问人:milkplus 提问时间:12/4/2010 最后编辑:starballmilkplus 更新时间:8/26/2023 访问量:1751647

问:

我有一个用 Node.js 编写的 Web 服务器,我想使用特定文件夹启动。我不确定如何在 JavaScript 中访问参数。我正在像这样运行节点:

$ node server.js folder

这是我的服务器代码。Node.js 帮助说这是可能的:server.js

$ node -h
Usage: node [options] script.js [arguments]

如何在 JavaScript 中访问这些参数?不知何故,我无法在网上找到这些信息。

javascript 节点 .js 参数 命令行参数

评论

0赞 250R 5/26/2012
使用 nconf 之类的东西以集中的方式管理您的配置可能是个好主意 github.com/flatiron/nconf 它可以帮助您使用配置文件、环境变量、命令行参数。
0赞 Joel Purra 1/26/2014
这是 configvention,我自己的、最小的、只读的 nconf 接口。

答:

3655赞 MooGoo 12/4/2010 #1

标准方法(无库)

参数存储在process.argv

以下是有关处理命令行参数的节点文档:

process.argv是包含命令行参数的数组。第一个元素是“node”,第二个元素是 JavaScript 文件的名称。接下来的元素将是任何其他命令行参数。

// print process.argv
process.argv.forEach(function (val, index, array) {
  console.log(index + ': ' + val);
});

这将生成:

$ node process-2.js one two=three four
0: node
1: /Users/mjr/work/node/process-2.js
2: one
3: two=three
4: four

评论

33赞 cuixiping 1/7/2016
第二个元素 (process.argv[1]) 可能是也可能不是 JS 文件。节点命令语法是节点 [选项] [ -e 脚本 | 脚本.js ] [参数] 或节点调试脚本.js [参数]。例如: 或者 ,我们可以将 process.execArgv 与 process.argv 一起使用node --harmony script.js balalanode --no-deprecation --enable-ssl2 script.js balala
5赞 Kid 10/11/2022
对于 node.js 文档,process.argv 不会返回这些特定于 node.js 的标志。就像你的例子一样--harmony
0赞 Slion 6/28/2023
出于某种原因,该代码没有在带有 tsx 的 TypeScript 中输出任何内容。参数在 .process.argv
6赞 zola25 8/16/2023
2023 年,节点运行时的新手,必须在 2016 年、2018 年走过这些答案,许多人声称是“新方式”。2023 年的 TLDR 如下所示:这个答案一直是正确的,只有 2 个陷阱,因为您需要忽略两个参数;它不会捕获在 node.exe 中/之前输入的参数,例如 --harmony node.exe - 但没关系,您可以在其他地方获得这些参数。其他值得注意的答案是能够更好地解析输入参数且可提取的库。minimist 就是其中之一,它不再被支持,但现在它似乎又活了过来,在一个不同的 repo 中。
974赞 Mauvis Ledford 4/24/2011 #2

为了像常规 javascript 函数一样规范化参数,我在我的 node.js shell 脚本中执行此操作:

var args = process.argv.slice(2);

请注意,第一个 arg 通常是 nodejs 的路径,第二个 arg 是您正在执行的脚本的位置。

评论

0赞 Marcin 7/27/2022
虽然这以简单的方式回答了问题,但请注意,此方法不支持标志,并且要求以严格的顺序传递参数。
0赞 kien_coi_1997 10/2/2022
@M-Cat:试试这个:for (let i=2; i<argv.length; i++) { switch (argv[i]) { case "--foo": foo=argv[++i]; break; case "--bar": bar=argv[++i]; break; default: throw new Error("unknown arg"); } }
137赞 gor 7/4/2011 #3

Optimist (节点优化主义者)

查看 optimist 库,它比手动解析命令行选项要好得多。

更新

Optimist 已弃用。试试 yargs,它是乐观主义者的活跃分叉。

评论

19赞 Thilo 9/15/2011
链接为 +1。github.com/joyent/node/wiki/modules#wiki-parsers-commandline 有相当长的命令行选项解析器列表
90赞 balupton 9/20/2011 #4

指挥官.js

非常适合定义您的选项、操作和参数。它还会为您生成帮助页面。

及时

如果您喜欢回调方法,则非常适合从用户那里获取输入。

协同提示

如果您喜欢生成器方法,则非常适合从用户那里获取输入。

评论

33赞 balupton 11/11/2013
@Evan Carroll 请不要编辑我的答案来推广我不使用的库 stackoverflow.com/posts/7483600/revisions 特别是因为您缺少一个功能,这些意见应该保存给模块作者的评论或拉取请求,而不是编辑其他人的答案。
61赞 Sean H. Worthington 6/17/2013 #5

如果您的脚本名为 myScript.js,并且您希望将名字和姓氏“Sean Worthington”作为如下所示的参数传递:

node myScript.js Sean Worthington

然后在脚本中编写:

var firstName = process.argv[2]; // Will be set to 'Sean'
var lastName = process.argv[3]; // Will be set to 'Worthington'
84赞 sgmonda 8/13/2013 #6

Stdio图书馆

在 NodeJS 中解析命令行参数的最简单方法是使用 stdio 模块。受 UNIX 实用程序的启发,它非常简单,如下所示:getopt

var stdio = require('stdio');
var ops = stdio.getopt({
    'check': {key: 'c', args: 2, description: 'What this option means'},
    'map': {key: 'm', description: 'Another description'},
    'kaka': {args: 1, required: true},
    'ooo': {key: 'o'}
});

如果使用以下命令运行前面的代码:

node <your_script.js> -c 23 45 --map -k 23 file1 file2

然后对象将如下所示:ops

{ check: [ '23', '45' ],
  args: [ 'file1', 'file2' ],
  map: true,
  kaka: '23' }

因此,您可以随心所欲地使用它。例如:

if (ops.kaka && ops.check) {
    console.log(ops.kaka + ops.check[0]);
}

还支持分组选项,因此您可以编写 .-om-o -m

此外,可以自动生成帮助/使用输出。如果您致电,您将收到以下内容:stdioops.printHelp()

USAGE: node something.js [--check <ARG1> <ARG2>] [--kaka] [--ooo] [--map]
  -c, --check <ARG1> <ARG2>   What this option means (mandatory)
  -k, --kaka                  (mandatory)
  --map                       Another description
  -o, --ooo

如果未给出强制选项(前面有错误消息)或错误指定(例如,如果为选项指定单个参数并且它需要 2),也会显示上一条消息。

您可以使用 NPM 安装 stdio 模块:

npm install stdio

评论

0赞 Sridhar Sarnobat 1/24/2022
奇怪的是,我得到了一个我设置的论点.我什至在库的第 2 版中尝试过这个。requires 1 argumentsrequired: false
0赞 Nir O. 12/18/2022
ops.printHelp() 对我不起作用。也许旧版本是真的?
0赞 sgmonda 12/18/2022
@NirO。在你的情况下,自动行为还不够吗?必须打印帮助。--help
0赞 Nir O. 12/19/2022
printHelp() 不起作用的事实只是掩盖了这篇文章可能已经过时的事实,其他读者应该注意,该库可能不再像这里描述的那样运行,仅此而已。我认为“必需”行为也与帖子不同,但我继续前进
0赞 Anh-Thi DINH 3/7/2023
我们可以放在哪里?ops<your_script.js>
9赞 Amadu Bah 12/10/2013 #7

您可以解析所有参数并检查它们是否存在。

文件:parse-cli-arguments.js:

module.exports = function(requiredArguments){
    var arguments = {};

    for (var index = 0; index < process.argv.length; index++) {
        var re = new RegExp('--([A-Za-z0-9_]+)=([A/-Za-z0-9_]+)'),
            matches = re.exec(process.argv[index]);

        if(matches !== null) {
            arguments[matches[1]] = matches[2];
        }
    }

    for (var index = 0; index < requiredArguments.length; index++) {
        if (arguments[requiredArguments[index]] === undefined) {
            throw(requiredArguments[index] + ' not defined. Please add the argument with --' + requiredArguments[index]);
        }
    }

    return arguments;
}

不仅仅是做:

var arguments = require('./parse-cli-arguments')(['foo', 'bar', 'xpto']);
132赞 Paul van Jaarsveld 12/12/2013 #8

这里有几个很好的答案,但这一切似乎都非常复杂。这与 bash 脚本访问参数值的方式非常相似,并且正如 MooGoo 指出的那样,它已经与 node.js 一起提供了标准。 (只是为了让刚接触 node.js 的人可以理解)

例:

$ node yourscript.js banana monkey

var program_name = process.argv[0]; //value will be "node"
var script_path = process.argv[1]; //value will be "yourscript.js"
var first_value = process.argv[2]; //value will be "banana"
var second_value = process.argv[3]; //value will be "monkey"
497赞 real_ate 7/9/2014 #9

最新的正确答案是使用 minimist 库。我们曾经使用node-optimist,但后来它被弃用了。

以下是直接从 minimist 文档中获取的如何使用它的示例:

var argv = require('minimist')(process.argv.slice(2));
console.dir(argv);

-

$ node example/parse.js -a beep -b boop
{ _: [], a: 'beep', b: 'boop' }

-

$ node example/parse.js -x 3 -y 4 -n5 -abc --beep=boop foo bar baz
{ _: [ 'foo', 'bar', 'baz' ],
  x: 3,
  y: 4,
  n: 5,
  a: true,
  b: true,
  c: true,
  beep: 'boop' }

评论

55赞 JK ABC 2/6/2015
实际上,此解决方案对于开发具有更多标志和参数的命令行工具更有帮助,并且应该得到更多的恕我直言。
8赞 Steam gamer 1/25/2022
如果你打算使用这个答案,请考虑使用更活跃的 fork minimist-lite,因为前者被放弃了。“最新的正确答案”是使用哪个是实际问题的答案......process.argv.slice(2)
1赞 aroth 10/18/2023
该库看起来很有用,尤其是在需要解析参数时。然而,“最新的正确答案”几乎从不引入额外的第三方库来做一些已经内置的事情。 无需任何其他库即可完成工作。process.argv.slice(2)
29赞 Zlatko 3/14/2015 #10

有一个应用程序可以做到这一点。好吧,模块。嗯,不止一个,可能是数百个。

Yargs 是有趣的之一,它的文档读起来很酷。

下面是 github/npm 页面中的一个示例:

#!/usr/bin/env node
var argv = require('yargs').argv;
console.log('(%d,%d)', argv.x, argv.y);
console.log(argv._);

输出在这里(它读取带有破折号等、短和长、数字等的选项)。

$ ./nonopt.js -x 6.82 -y 3.35 rum
(6.82,3.35)
[ 'rum' ] 
$ ./nonopt.js "me hearties" -x 0.54 yo -y 1.12 ho
(0.54,1.12)
[ 'me hearties', 'yo', 'ho' ]
35赞 Lloyd 11/16/2015 #11

command-line-args 值得一看!

您可以使用主要符号标准设置选项(了解更多)。这些命令都是等效的,设置相同的值:

$ example --verbose --timeout=1000 --src one.js --src two.js
$ example --verbose --timeout 1000 --src one.js two.js
$ example -vt 1000 --src one.js two.js
$ example -vt 1000 one.js two.js

若要访问这些值,请首先创建一个选项定义列表,描述应用程序接受的选项。type 属性是一个 setter 函数(提供的值通过此函数传递),使您可以完全控制接收到的值。

const optionDefinitions = [
  { name: 'verbose', alias: 'v', type: Boolean },
  { name: 'src', type: String, multiple: true, defaultOption: true },
  { name: 'timeout', alias: 't', type: Number }
]

接下来,使用 commandLineArgs() 解析选项:

const commandLineArgs = require('command-line-args')
const options = commandLineArgs(optionDefinitions)

options现在看起来像这样:

{
  src: [
    'one.js',
    'two.js'
  ],
  verbose: true,
  timeout: 1000
}

高级用法

除了上述典型用法外,您还可以配置命令行参数以接受更高级的语法形式。

基于命令的语法(git 样式),格式如下:

$ executable <command> [options]

例如。

$ git commit --squash -m "This is my commit message"

命令和子命令语法(docker 样式),格式为:

$ executable <command> [options] <sub-command> [options]

例如。

$ docker run --detached --image centos bash -c yum install -y httpd

使用指南生成

可以使用命令行用法生成使用指南(通常在设置时打印)。请参阅以下示例并阅读文档以获取有关如何创建它们的说明。--help

典型的使用指南示例。

usage

polymer-cli 使用指南就是一个很好的现实生活中的例子。

usage

延伸阅读

还有很多东西需要学习,请参阅 wiki 以获取示例和文档。

14赞 Piyush Sagar 1/11/2016 #12

传递、解析参数是一个简单的过程。Node 为您提供了 process.argv 属性,该属性是一个字符串数组,这些字符串是调用 Node 时使用的参数。 数组的第一个条目是 Node 可执行文件,第二个条目是脚本的名称。

如果使用以下附件运行脚本

$ node args.js arg1 arg2

文件 : args.js

console.log(process.argv)

你会得到像这样的数组

 ['node','args.js','arg1','arg2']
431赞 dthree 1/14/2016 #13

2018年基于当前野外趋势的答案:


Vanilla javascript 参数解析:

const args = process.argv;
console.log(args);

这将返回:

$ node server.js one two=three four
['node', '/home/server.js', 'one', 'two=three', 'four']

官方文档


最常用的用于参数解析的 NPM 包:

Minimist:用于最小参数解析。

Commander.js:最常采用的参数解析模块。

:指挥官.js的轻量级替代品

Yargs:更复杂的参数解析(重度)。

Vorpal.js:具有参数解析的成熟/交互式命令行应用程序。

评论

141赞 joonas.fi 10/14/2016
“$ npm install -g yargs” 生成了 1.9 MB 的 JavaScript 代码。当 argv 解析器库需要两兆字节的代码时,这种疯狂何时会结束?增加攻击面,浪费RAM等...
0赞 Subramanya Rao 11/23/2021
选择自定义参数的简单方法: const list_arg = process.argv.filter((arg) => (['-list', '-l'].includes(arg))).toString();
11赞 Abdennour TOUMI 7/15/2016 #14
npm install ps-grab

如果你想运行这样的东西:

node greeting.js --user Abdennour --website http://abdennoor.com 

--

var grab=require('ps-grab');
grab('--username') // return 'Abdennour'
grab('--action') // return 'http://abdennoor.com'

或者类似的东西:

node vbox.js -OS redhat -VM template-12332 ;

--

var grab=require('ps-grab');
grab('-OS') // return 'redhat'
grab('-VM') // return 'template-12332'
8赞 Evren Kutar 8/10/2016 #15

您可以使用 访问命令行参数。我使用下面的解决方案将参数解析为一个对象,这样我就可以通过名称获取我想要的参数。system.args

var system = require('system');

var args = {};
system.args.map(function(x){return x.split("=")})
    .map(function(y){args[y[0]]=y[1]});

现在,您不需要知道参数的索引。像这样使用它args.whatever

注意:您应该使用命名参数,例如使用 这个解决方案。file.js x=1 y=2

-3赞 MatCas 6/8/2017 #16

如果需要的话,一个简单的片段:

var fs = require('fs'), objMod = {};

process.argv.slice(2).map(function(y, i) {
  y = y.split('=');
  if (y[0] && y[1]) objMod[y[0]] = y[1];
  else console.log('Error in argument number ' + (i+1));
});

评论

1赞 barwnikk 3/23/2018
为什么要使用 require('fs')?
5赞 Cassidy 10/4/2017 #17

没有库

如果你想在 vanilla JS/ES6 中做到这一点,你可以使用以下解决方案

仅在 NodeJS > 6 中工作

const args = process.argv
  .slice(2)
  .map((val, i)=>{
    let object = {};
    let [regexForProp, regexForVal] = (() => [new RegExp('^(.+?)='), new RegExp('\=(.*)')] )();
    let [prop, value] = (() => [regexForProp.exec(val), regexForVal.exec(val)] )();
    if(!prop){
      object[val] = true;
      return object;
    } else {
      object[prop[1]] = value[1] ;
      return object
    }
  })
  .reduce((obj, item) => {
    let prop = Object.keys(item)[0];
    obj[prop] = item[prop];
    return obj;
  }, {});

还有这个命令

node index.js host=http://google.com port=8080 production

将产生以下结果

console.log(args);//{ host:'http://google.com',port:'8080',production:true }
console.log(args.host);//http://google.com
console.log(args.port);//8080
console.log(args.production);//true

p.s. 请更正 map 和 reduce 函数中的代码 如果您找到更优雅的解决方案,谢谢;)

评论

1赞 Joseph Merdrignac 10/13/2017
我同意,但它可能会更短,不是吗?let args = process.argv.slice(2).reduce((acc, arg) => { let [k, v] = arg.split('=') acc[k] = v return acc }, {})
21赞 Joseph Merdrignac 10/13/2017 #18

使用库:使用 Array.prototype.reduce()

const args = process.argv.slice(2).reduce((acc, arg) => {

    let [k, v = true] = arg.split('=')
    acc[k] = v
    return acc

}, {})

对于此命令node index.js count=2 print debug=false msg=hi

console.log(args) // { count: '2', print: true, debug: 'false', msg: 'hi' }

我们可以改变

    let [k, v = true] = arg.split('=')
    acc[k] = v

作者(更长)

    let [k, v] = arg.split('=')
    acc[k] = v === undefined ? true : /true|false/.test(v) ? v === 'true' : /[\d|\.]+/.test(v) ? Number(v) : v

自动解析布尔值和数字

console.log(args) // { count: 2, print: true, debug: false, msg: 'hi' }
1赞 Adeojo Emmanuel IMM 4/24/2018 #19

如节点文档中所述 process.argv 属性返回一个数组,其中包含启动 Node.js 进程时传递的命令行参数。

例如,假设 process-args.js 的以下脚本:

// print process.argv
process.argv.forEach((val, index) => {
   console.log(`${index}: ${val}`);
});

启动 Node.js 进程:

 $ node process-args.js one two=three four

将生成输出:

0: /usr/local/bin/node
1: /Users/mjr/work/node/process-args.js
2: one
3: two=three
4: four
1赞 S.Mishra 4/26/2018 #20

大多数人都给出了很好的答案。我也想在这里贡献一些东西。我使用库来遍历我们在启动应用程序时传递的所有命令行参数来提供答案:lodash

// Lodash library
const _ = require('lodash');

// Function that goes through each CommandLine Arguments and prints it to the console.
const runApp = () => {
    _.map(process.argv, (arg) => {
        console.log(arg);
    });
};

// Calling the function.
runApp();

要运行上述代码,只需运行以下命令:

npm install
node index.js xyz abc 123 456

结果将是:

xyz 
abc 
123
456
5赞 Rubin bhandari 5/22/2018 #21

在 Node.js 中检索参数的最简单方法是通过 process.argv 数组。这是一个全局对象,无需导入任何其他库即可使用。您只需要将参数传递给 Node.js 应用程序,就像我们之前展示的那样,这些参数可以通过 process.argv 数组在应用程序中访问。

process.argv 数组的第一个元素将始终是指向节点可执行文件的文件系统路径。第二个元素是正在执行的 JavaScript 文件的名称。第三个元素是用户实际传递的第一个参数。

'use strict';

for (let j = 0; j < process.argv.length; j++) {  
    console.log(j + ' -> ' + (process.argv[j]));
}

此脚本所做的只是遍历 process.argv 数组并打印索引以及存储在这些索引中的元素。如果您质疑您收到的参数以及顺序,它对于调试非常有用。

您还可以使用 yargs 等库来处理 commnadline 参数。

3赞 bhwp 6/8/2018 #22

process.argv是你的朋友,Node JS 原生支持捕获命令行参数。请参阅以下示例:

process.argv.forEach((val, index) => {
  console.log(`${index}: ${val}`);
})
25赞 Nouman Dilshad 7/2/2018 #23

proj.js

for(var i=0;i<process.argv.length;i++){
  console.log(process.argv[i]);
}

终端:

nodemon app.js "arg1" "arg2" "arg3"

结果:

0 'C:\\Program Files\\nodejs\\node.exe'
1 'C:\\Users\\Nouman\\Desktop\\Node\\camer nodejs\\proj.js'
2 'arg1' your first argument you passed.
3 'arg2' your second argument you passed.
4 'arg3' your third argument you passed.

说明:

  1. 计算机中 node.exe 的目录 (C:\Program Files\nodejs\node.exe)
  2. 项目文件的目录 (proj.js)
  3. 节点的第一个参数 (arg1)
  4. 节点的第二个参数 (arg2)
  5. 节点的第三个参数 (arg3)

您的实际参数从数组的第二个索引开始,即 .argvprocess.argv[2]

34赞 grebenyuksv 7/30/2018 #24

这是我对命名参数的 0-dep 解决方案:

const args = process.argv
    .slice(2)
    .map(arg => arg.split('='))
    .reduce((args, [value, key]) => {
        args[value] = key;
        return args;
    }, {});

console.log(args.foo)
console.log(args.fizz)

例:

$ node test.js foo=bar fizz=buzz
bar
buzz

注意:当参数包含 .这仅适用于非常简单的使用。=

6赞 Akshay Rajput 12/12/2018 #25

虽然上面的答案很完美,而且已经有人建议过yargs,但使用这个包真的很容易。 这是一个不错的包,它使将参数传递到命令行变得非常容易。

npm i yargs
const yargs = require("yargs");
const argv = yargs.argv;
console.log(argv);

请访问 https://yargs.js.org/ 了解更多信息。

评论

0赞 user3285954 11/4/2019
Yargs 不会影响参数在命令行上的传递方式,它只有助于在代码中读取它们。
125赞 Michael Warner 1/9/2019 #26

没有带有标志格式化为简单对象的库

function getArgs () {
    const args = {};
    process.argv
        .slice(2, process.argv.length)
        .forEach( arg => {
        // long arg
        if (arg.slice(0,2) === '--') {
            const longArg = arg.split('=');
            const longArgFlag = longArg[0].slice(2,longArg[0].length);
            const longArgValue = longArg.length > 1 ? longArg[1] : true;
            args[longArgFlag] = longArgValue;
        }
        // flags
        else if (arg[0] === '-') {
            const flags = arg.slice(1,arg.length).split('');
            flags.forEach(flag => {
            args[flag] = true;
            });
        }
    });
    return args;
}
const args = getArgs();
console.log(args);

例子

简单

输入

node test.js -D --name=Hello

输出

{ D: true, name: 'Hello' }

真实世界

输入

node config/build.js -lHRs --ip=$HOST --port=$PORT --env=dev

输出

{ 
  l: true,
  H: true,
  R: true,
  s: true,
  ip: '127.0.0.1',
  port: '8080',
  env: 'dev'
}

评论

0赞 hastrb 11/12/2021
.slice(2, process.argv.length)第二个 arg 不是多余的吗? 默认情况下,转到字符串的末尾。.slice()
8赞 isacvale 2/26/2019 #27

传递参数很容易,接收参数只需读取 process.argv 数组 Node 基本上可以从任何地方访问。但是你肯定想把它们当作键/值对来读,所以你需要一个脚本来解释它。

约瑟夫·梅德里尼亚克(Joseph Merdrignac)使用reduce发布了一个漂亮的,但它依赖于语法而不是和。为了使用第二个标准,我把它写得更丑陋、更长,我会把它作为答案发布,因为它不适合作为评论。但它确实完成了工作。key=value-k value--key value

   const args = process.argv.slice(2).reduce((acc,arg,cur,arr)=>{
     if(arg.match(/^--/)){
       acc[arg.substring(2)] = true
       acc['_lastkey'] = arg.substring(2)
     } else
     if(arg.match(/^-[^-]/)){
       for(key of arg.substring(1).split('')){
         acc[key] = true
         acc['_lastkey'] = key
       }
     } else
       if(acc['_lastkey']){
         acc[acc['_lastkey']] = arg
         delete acc['_lastkey']
       } else
         acc[arg] = true
     if(cur==arr.length-1)
       delete acc['_lastkey']
     return acc
   },{})

使用此代码,命令将为您提供以下对象node script.js alpha beta -charlie delta --echo foxtrot


args = {
 "alpha":true,
 "beta":true,
 "c":true,
 "h":true,
 "a":true,
 "r":true
 "l":true,
 "i":true,
 "e":"delta",
 "echo":"foxtrot"
}
3赞 tibalt 9/13/2019 #28

ES6 风格的无依赖解决方案:

const longArgs = arg => {
    const [ key, value ] = arg.split('=');
    return { [key.slice(2)]: value || true }
};

const flags = arg => [...arg.slice(1)].reduce((flagObj, f) => ({ ...flagObj, [f]: true }), {});


const args = () =>
    process.argv
        .slice(2)
        .reduce((args, arg) => ({
            ...args,
            ...((arg.startsWith('--') && longArgs(arg)) || (arg[0] === '-' && flags(arg)))
        }), {});

console.log(args());

评论

0赞 Endless 2/27/2021
像这样写太多 ES6 会让代码乍一看感觉不可读
0赞 TruMan1 10/22/2022
这看起来像汇编语言
20赞 Manvel 10/1/2019 #29

基于标准输入的解析参数 (--key=value )

const argv = (() => {
    const arguments = {};
    process.argv.slice(2).map( (element) => {
        const matches = element.match( '--([a-zA-Z0-9]+)=(.*)');
        if ( matches ){
            arguments[matches[1]] = matches[2]
                .replace(/^['"]/, '').replace(/['"]$/, '');
        }
    });
    return arguments;
})();

命令示例

node app.js --name=stackoverflow --id=10 another-argument --text="Hello World"

argv的结果:console.log(argv)

{
    name: "stackoverflow",
    id: "10",
    text: "Hello World"
}
6赞 rmolinamir 3/4/2020 #30

没有库的 TypeScript 解决方案:

interface IParams {
  [key: string]: string
}

function parseCliParams(): IParams {
  const args: IParams = {};
  const rawArgs = process.argv.slice(2, process.argv.length);
  rawArgs.forEach((arg: string, index) => {
    // Long arguments with '--' flags:
    if (arg.slice(0, 2).includes('--')) {
      const longArgKey = arg.slice(2, arg.length);
      const longArgValue = rawArgs[index + 1]; // Next value, e.g.: --connection connection_name
      args[longArgKey] = longArgValue;
    }
    // Shot arguments with '-' flags:
    else if (arg.slice(0, 1).includes('-')) {
      const longArgKey = arg.slice(1, arg.length);
      const longArgValue = rawArgs[index + 1]; // Next value, e.g.: -c connection_name
      args[longArgKey] = longArgValue;
    }
  });
  return args;
}

const params = parseCliParams();
console.log('params: ', params);

输入:ts-node index.js -p param --parameter parameter

输出:{ p: 'param ', parameter: 'parameter' }

3赞 Giorgio Robino 9/24/2020 #31

我扩展了该函数只是为了获得命令,以及标志(,)和命名的args():getArgs-f--anotherflag--data=blablabla

  1. 模块
/**
 * @module getArgs.js
 * get command line arguments (commands, named arguments, flags)
 *
 * @see https://stackoverflow.com/a/54098693/1786393
 *
 * @return {Object}
 *
 */
function getArgs () {
  const commands = []
  const args = {}
  process.argv
    .slice(2, process.argv.length)
    .forEach( arg => {
      // long arg
      if (arg.slice(0,2) === '--') {
        const longArg = arg.split('=')
        const longArgFlag = longArg[0].slice(2,longArg[0].length)
        const longArgValue = longArg.length > 1 ? longArg[1] : true
        args[longArgFlag] = longArgValue
     }
     // flags
      else if (arg[0] === '-') {
        const flags = arg.slice(1,arg.length).split('')
        flags.forEach(flag => {
          args[flag] = true
        })
      }
     else {
      // commands
      commands.push(arg)
     } 
    })
  return { args, commands }
}


// test
if (require.main === module) {
  // node getArgs test --dir=examples/getUserName --start=getUserName.askName
  console.log( getArgs() )
}

module.exports = { getArgs }

  1. 使用示例:
$ node lib/getArgs test --dir=examples/getUserName --start=getUserName.askName
{
  args: { dir: 'examples/getUserName', start: 'getUserName.askName' },
  commands: [ 'test' ]
}

$ node lib/getArgs --dir=examples/getUserName --start=getUserName.askName test tutorial
{
  args: { dir: 'examples/getUserName', start: 'getUserName.askName' },
  commands: [ 'test', 'tutorial' ]
}

4赞 Carson 7/30/2021 #32

您可以从 process.argv() 获取命令行信息

而且我不想将问题限制在.相反,我想把它变成如何将字符串解析为参数。node.js

console.log(ArgumentParser(`--debug --msg="Hello World" --title="Test" --desc=demo -open --level=5 --MyFloat=3.14`))

输出

{
  "debug": true,
  "msg": "Hello World",
  "title": "Test",
  "desc": "demo",
  "open": true,
  "level": 5,
  "MyFloat": 3.14
}

法典

纯 javascript,无需依赖

// 👇 Below is Test
(() => {
  window.onload = () => {
    const testArray = [
      `--debug --msg="Hello World" --title="Test" --desc=demo -open --level=5 --MyFloat=3.14`,
    ]
    for (const testData of testArray) {
      try {
        const obj = ArgumentParser(testData)
        console.log(obj)
      } catch (e) {
        console.error(e.message)
      }
    }
  }
})()

// 👇 Script
class ParserError extends Error {

}

function Cursor(str, pos) {
  this.str = str
  this.pos = pos
  this.MoveRight = (step = 1) => {
    this.pos += step
  }

  this.MoveToNextPara = () => {
    const curStr = this.str.substring(this.pos)
    const match = /^(?<all> *--?(?<name>[a-zA-Z_][a-zA-Z0-9_]*)(=(?<value>[^-]*))?)/g.exec(curStr) // https://regex101.com/r/k004Gv/2
    if (match) {
      let {groups: {all, name, value}} = match

      if (value !== undefined) {
        value = value.trim()
        if (value.slice(0, 1) === '"') { // string
          if (value.slice(-1) !== '"') {
            throw new ParserError(`Parsing error: '"' expected`)
          }
          value = value.slice(1, -1)
        } else { // number or string (without '"')
          value = isNaN(Number(value)) ? String(value) : Number(value)
        }
      }

      this.MoveRight(all.length)
      return [name, value ?? true] // If the value is undefined, then set it as ture.
    }
    throw new ParserError(`illegal format detected. ${curStr}`)
  }
}

function ArgumentParser(str) {
  const obj = {}
  const cursor = new Cursor(str, 0)
  while (1) {
    const [name, value] = cursor.MoveToNextPara()
    obj[name] = value
    if (cursor.pos === str.length) {
      return obj
    }
  }
}

49赞 Andrew Odri 10/2/2021 #33

简单 + ES6 + 无依赖 + 支持布尔标志

const process = require( 'process' );

const argv = key => {
  // Return true if the key exists and a value is defined
  if ( process.argv.includes( `--${ key }` ) ) return true;

  const value = process.argv.find( element => element.startsWith( `--${ key }=` ) );

  // Return null if the key does not exist and a value is not defined
  if ( !value ) return null;
  
  return value.replace( `--${ key }=` , '' );
}

输出:

  • 如果调用了 then 将返回node app.jsargv('foo')null
  • 如果调用了 then 将返回node app.js --fooargv('foo')true
  • 如果调用了 then 将返回node app.js --foo=argv('foo')''
  • 如果调用了 then 将返回node app.js --foo=barargv('foo')'bar'

评论

0赞 temporary_user_name 4/19/2022
不是为了 ?我很困惑它是如何通过第一个条件的。if ( process.argv.includes( `--${ key }` ) )true--foo=bar
1赞 Andrew Odri 4/20/2022
@temporary_user_name啊,好问题...... 测试 argv 数组中的匹配值,而不是每个 argv 条目中的子字符串。因此,该值必须完全匹配:即使用包含元素测试 argv 将不匹配,这将是数组中的单独值。下一行显示子字符串搜索的外观。includes--foo--foo=barprocess.argv.find
0赞 temporary_user_name 4/20/2022
哦,现在你说出来了,这太明显了。我完全知道这一点,并没有在想。谢谢你的提醒。
2赞 Andrew Odri 4/20/2022
@temporary_user_name 一切都很好...对于读者来说,看到 ES6 语法糖和功能的权衡是件好事......短小精悍并不总是等同于可读:P
1赞 Preston L. Bannister 12/15/2021 #34

最初的问题是要求传递命令行参数,而不是更复杂的参数解析。然而,对于所有复杂的答案,他们都错过了一个简单而有用的变体。

您知道 Unix shell 支持命名参数吗?这可以追溯到 1980 年代的原始 Bourne shell。用法很简单:

$ FOO=one BAR=two nodejs myscript.js

要在 Javascript 中获取参数:

var foo = process.env.FOO;
var bar = process.env.BAR;

一旦你超过两个或三个参数,命名参数就更容易阅读。可选参数简单,顺序不固定。

(这甚至可能在 Windows 上工作,最近支持 Unix shell。

此外,令人震惊的是,很少有 Unix 程序员知道这种用法。:)

评论

0赞 CherryDT 2/24/2022
这些不是“命名参数”,而是环境变量。
0赞 Preston L. Bannister 2/24/2022
它们是参数,它们被命名。它们是环境变量是偶然的。或者你有其他定义?:)
0赞 CherryDT 2/24/2022
命名参数为 。环境变量具有完全不同的语义,例如也传递给所有子进程(这两者都是一个问题 - 你可能传递了一些你没有预料到的东西,你可能会转发一些你不想要的东西),并且除非在 WSLENV 中单独指定,否则不会跨 WSL 互操作边界传递。这些不同的语义是它们在名称中包含环境的原因。--myvalue=abc
0赞 Preston L. Bannister 3/6/2022
再一次,然后我放弃了这个线程。我们正在将命名参数传递给程序。是的,语义略有不同,但仅此而已。有没有读过调用“C”main()的库代码?命令行和环境都只是指向字符缓冲区的指针。对于我编写的大多数/许多(小)工具,在环境中传递的参数的全局性略高一些,这并没有实际问题。对于较大的作品,我为子进程构建环境。(限制风险的良好做法。在这一点上,我认为我们不会同意。
0赞 CherryDT 3/6/2022
然而,为已经有名字的事物发明新名称,特别是如果该新名称与其他类似事物的名称相冲突,则完全令人困惑。已命名的命令行参数已存在,其形式为 或 .是的,您可以使用环境变量将某个名称标识的字符串值传递给进程,但这并不能使它们成为命名参数,因为该术语已经具有另一种含义。将 spritz(含苏打水的葡萄酒)称为起泡酒同样是错误和令人困惑的,即使它尝起来像葡萄酒并且是起泡酒,不是吗?--arg=xyz--arg xyz
4赞 Idan Krupnik 4/2/2022 #35

NodeJS 公开了一个名为 的全局变量。process

我们可以使用:

process.argv

获取命令行参数,传递给我们的脚本。

的输出将按以下顺序列出:process.argv

[
full-path-to-node-executable,
full-path-to-the-script-file
...additonal-arguments-we-provide
]
16赞 Hender 4/18/2022 #36

在节点代码中需要内置的进程库。

const {argv} = require('process')

使用它们的参数运行程序。

$ node process-args.js one two=three four

argv 是以下数组:

argv[0] = /usr/bin/node
argv[1] = /home/user/process-args.js
argv[2] = one
argv[3] = two=three
argv[4] = four
2赞 sabin maharjan 10/12/2022 #37

使用 minimist npm 包。这是最简单的方法,无需担心任何事情。

const arguments = require("minimist")(process.argv.slice(2)); 
// get the extra argument of command line . 
eg node app.js --process="sendEmailWithReminder"

我们也可以在 Windows 任务调度程序中使用它。

enter image description here

enter image description here

enter image description here

15赞 mbelsky 12/13/2022 #38

原生实验方法

Nodejs 团队在 18.3.0 和 16.17.0 版本中添加了 util.parseArgs 函数。因此,如果您使用这些或更高版本的 nodejs,则可以使用此本机解决方案解析命令行参数。

文档中的用法示例:

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

const args = process.argv;
const options = {
  foo: {
    type: 'boolean',
    short: 'f'
  },
  bar: {
    type: 'string'
  }
};
const {
  values,
  positionals
} = parseArgs({ args, options, allowPositionals: true });

console.log(values);
console.log(positionals);

输出示例:

$ node parseargs.js -f --bar b
[Object: null prototype] { foo: true, bar: 'b' }
[
  '/Users/mbelsky/.nvm/versions/node/v18.12.1/bin/node',
  '/Users/mbelsky/parseargs.js'
]
-1赞 akshat chawla 3/21/2023 #39

您可以使用 Rest 运算符在一个函数中接受 n 个参数并使用它 像这样,我发布了一个示例程序,希望它能帮助您理解重点。

    function sum(...theArgs) {
  let total = 0;
  for (const arg of theArgs) {
    total += arg;
  }
  return total;
}

console.log(sum(1, 2, 3));
// Expected output: 6

console.log(sum(1, 2, 3, 4));
// Expected output: 10

    enter code here

评论

0赞 Can Rau 10/7/2023
只是为了澄清反对票(不是我),问题是关于 CLI(命令行界面)参数而不是函数参数的
6赞 John Lee 5/23/2023 #40

解决方案:使用 Set 解决使用简单参数(无键 + 值)时的位置问题。

例如,两个命令将返回相同的结果:

node server.js detail json
node server.js json detail
const args = new Set(process.argv.slice(2));

然后可以使用或不用担心位置。args.has('detail')args.has('json')

评论

0赞 Can Rau 10/7/2023
非常喜欢🙏它,以防万一一个不错的添加可能是小写的参数,例如new Set(process.argv.slice(2).map((a) => a.toLowerCase()));
0赞 xinthose 6/29/2023 #41

打字稿的方式来做到这一点。

npm i minimist @types/minimist

app.ts

// import
import { MyProgram } from './main';

// libraries
import minimist from 'minimist';

// interfaces
import { ParsedArgs } from 'minimist';

// code
const args: ParsedArgs = minimist(process.argv.slice(2));

let app = new MyProgram(args.a).getApp();
export { app };

使用 gulp 编译为 JavaScript 后运行的命令

node app.js -a MyParam

评论

0赞 jpaugh 12/4/2023
用户问题的答案是 。你的答案的其余部分增加了什么好处?minimist 提供了什么价值?process.argv.slice(2)process.argv