ChatGPT解决这个技术问题 Extra ChatGPT

如何将命令行参数传递给 Node.js 程序?

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

$ node server.js folder

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

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

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

使用 nconf 之类的工具以集中方式管理配置可能是个好主意。github.com/flatiron/nconf它可以帮助您处理配置文件、环境变量、命令行参数。
这里是 configvention,我自己的、最小的、只读的 nconf 接口。

u
user5532169

标准方法(无库)

参数存储在 process.argv

这里是the node docs on handling command line args:

process.argv 是一个包含命令行参数的数组。第一个元素是“节点”,第二个元素是 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

第二个元素(process.argv[1])可能是也可能不是 js 文件。节点命令语法为 node [options] [ -e script | script.js ] [arguments]node debug script.js [arguments]。例如: node --harmony script.js balalanode --no-deprecation --enable-ssl2 script.js balala ,我们可以将 process.execArgvprocess.argv 一起使用
b
bjb568

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

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

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


请注意,我在 4 年前写了这个答案,而我正在运行的代码今天仍然可以 100% 运行。仍然与最新版本的节点保持同步,并且仍然是零问题:这只是一个简单的 shell 脚本。不是一个充满 JS 库的大型全局对象的一部分。我今天仍然支持我的答案。我将在 4 年后再次更新。
已经6年多了。任何更新?
@Nuno 我刚刚在 Node v16.13.2 (2022-01-11) 上测试了我的原始答案,是的,它在发布 11 年后仍然可以正常工作。 :)
让我们在接下来的五年里看到 process.argv 的工作;)
r
real_ate

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

这是一个直接取自极简主义文档的如何使用它的示例:

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' }

实际上,这个解决方案对于开发具有更多标志和参数的命令行工具更有帮助,并且应该更多地支持恕我直言。
如果您要使用此答案,请考虑使用更活跃的分叉 minimist-lite,因为前者已被放弃。 “最新的正确答案”将使用 process.argv.slice(2) 这是实际问题的答案......
d
dthree

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

香草 javascript 参数解析:

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

这将返回:

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

Official docs

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

Minimist:用于最少的参数解析。

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

Meow:Commander.js 的更轻量级替代品

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

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


“$ npm install -g yargs”产生了 1.9 MB 的 JavaScript 代码。当一个 argv 解析器库需要两兆字节的代码时,这种疯狂何时结束?增加攻击面,浪费内存等...
选择自定义 arg 的简单方法: const list_arg = process.argv.filter((arg) => (['-list', '-l'].includes(arg))).toString();
S
Sanghyun Lee

乐观主义者(节点乐观主义者)

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

更新

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


+1 链接。 github.com/joyent/node/wiki/modules#wiki-parsers-commandline 上有很长的命令行选项解析器列表
P
Paul van Jaarsveld

这里有几个很好的答案,但这一切似乎都非常复杂。这与 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"

C
Community

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

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'
}

.slice(2, process.argv.length) 第二个参数不是多余的吗? .slice() 默认转到字符串的末尾。
b
balupton

指挥官.js

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

及时

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

共同提示

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


@Evan Carroll 请不要编辑我的答案来推广我不使用 stackoverflow.com/posts/7483600/revisions 的库,特别是因为您所追求的功能缺失,此类意见应保存以供评论或向模块作者提出请求,而不是编辑对别人的回答。
s
sgmonda

标准库

在 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

此外,stdio 可以自动生成帮助/使用输出。如果您调用 ops.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

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

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

npm install stdio

奇怪的是,我设置了 required: false 的参数得到了 requires 1 arguments。我什至用库的第 2 版尝试过这个。
r
riper

如果您的脚本名为 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'

L
Lloyd

command-line-args值得一看!

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

$ 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

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

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
}

高级用法

除了上述典型用法,您还可以配置 command-line-args 以接受更高级的语法形式。

Command-based syntax(git 风格)的形式:

$ executable <command> [options]

例如。

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

Command and sub-command syntax(泊坞窗样式)的形式:

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

例如。

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

使用指南生成

可以使用 command-line-usage 生成使用指南(通常在设置 --help 时打印)。有关如何创建它们的说明,请参阅下面的示例和 read the documentation

一个典型的使用指南示例。

https://raw.githubusercontent.com/75lb/command-line-usage/master/example/screens/footer.png

polymer-cli 使用指南是一个很好的真实示例。

https://raw.githubusercontent.com/75lb/command-line-usage/master/example/screens/polymer.png

延伸阅读

还有很多要学习的内容,请参阅 the wiki 以获取示例和文档。


S
Stan James

这是我的命名参数的 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

注意:当参数包含 = 时,这自然会失败。这仅用于非常简单的用法。


A
Andrew Odri

简单 + 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 }=` , '' );
}

输出:

如果使用 node app.js 调用,则 argv('foo') 将返回 null

如果使用 node app.js --foo 调用,则 argv('foo') 将返回 true

如果使用 node app.js --foo= 调用,则 argv('foo') 将返回 ''

如果使用 node app.js --foo=bar 调用,则 argv('foo') 将返回 'bar'


您的解决方案非常时尚。谢谢!
if ( process.argv.includes( `--${ key }` ) ) 不是 --foo=bartrue 吗?我很困惑它是如何通过第一个条件的。
@temporary_user_name 啊,好问题... includes 正在测试 argv 数组中的匹配值,而不是每个 argv 条目中的子字符串。因此该值必须完全匹配:即测试 argv 并包含 --foo 元素将不匹配 --foo=bar,这将是数组中的单独值。下一行 process.argv.find 显示了子字符串搜索的样子。
哦,现在你这么说,太明显了。我完全知道这一点,并没有在想。谢谢你提醒我。
@temporary_user_name 一切都好...对于读者来说,看到 ES6 语法糖和功能的权衡是件好事...简短并不总是等于可读:P
K
Kevin Burke

有一个应用程序。嗯,模块。嗯,不止一个,可能有数百个。

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' ]

N
Nouman Dilshad

项目.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.

解释:

您机器中 node.exe 的目录 (C:\Program Files\nodejs\node.exe) 您的项目文件的目录 (proj.js) 您对节点的第一个参数 (arg1) 您对节点的第二个参数 (arg2) 您的节点的第三个参数(arg3)

您的实际参数从 argv 数组的 second 索引开始,即 process.argv[2]


M
Manvel

基于标准输入( --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"
}

J
Joseph Merdrignac

没有库:使用 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' }

P
Piyush Sagar

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

如果您使用以下参数运行脚本

$ node args.js arg1 arg2

文件:args.js

console.log(process.argv)

你会得到像

 ['node','args.js','arg1','arg2']

A
Abdennour TOUMI
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'

E
Evren Kutar

您可以使用 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 之类的命名参数来使用此解决方案。


A
Amadu Bah

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

文件: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']);

i
isacvale

传递参数很容易,接收它们只是读取 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"
}

A
Akshay Rajput

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

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

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


Yargs 不会影响参数在命令行上的传递方式,它只有助于在代码中读取它们。
r
rmolinamir

没有库的 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' }


H
Hender

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

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

C
Cassidy

没有图书馆

如果您想在 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

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


我同意,但它可以更短,不是吗? let args = process.argv.slice(2).reduce((acc, arg) => { let [k, v] = arg.split('=') acc[k] = v return acc }, {})
R
Rubin bhandari

在 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 之类的库来处理命令行参数。


S
Suraj Rao

process.argv 是您的朋友,Node JS 原生支持捕获命令行参数。见下面的例子::

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

s
shreyasm-dev

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());

像这样写太多 es6 会让人第一眼觉得代码不可读
C
Carson

您可以从 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,不需要依赖

// 👇 下面是测试 (() => { 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 ) } } } })() // 👇 脚本类 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 = /^(? *--?(?[a-zA -Z_][a-zA-Z0-9_]*)(=(?<值>[^-]*))?)/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(`ParserError(`ParserError: '"' expected`) } value = value.slice(1, -1 ) } else { // 数字或字符串(不带 '"') value = isNaN(Number(value)) ? String(value) : Number(value) } } this.MoveRight(all.length) return [name, value ?? true] // 如果该值未定义,则将其设置为 ture。 } throw new ParserError(`检测到非法格式。${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 } } }