[Javascript] Come posso passare gli argomenti della riga di comando a un programma nodejs?


Answers

Per normalizzare gli argomenti come una normale funzione javascript, lo faccio nei miei script della shell node.js:

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

Si noti che il primo argomento è in genere il percorso per nodejs e il secondo argomento è la posizione dello script che si sta eseguendo.

Question

Ho un server web scritto in Node.js e vorrei avviare con una cartella specifica. Non sono sicuro di come accedere agli argomenti in JavaScript. Sto usando un nodo come questo:

$ node server.js folder

qui server.js è il mio codice server. L'aiuto di Node.js dice che questo è possibile:

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

Come potrei accedere a quegli argomenti in JavaScript? In qualche modo non sono stato in grado di trovare queste informazioni sul web.




command-line-args vale la pena dare un'occhiata!

È possibile impostare le opzioni utilizzando gli standard di notazione principale ( ulteriori informazioni ). Questi comandi sono tutti equivalenti, impostando gli stessi valori:

$ 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

Per accedere ai valori, innanzitutto creare un elenco di definizioni di opzioni che descrivono le opzioni accettate dall'applicazione. La proprietà type è una funzione setter (il valore fornito viene passato attraverso questo), dandoti il ​​pieno controllo sul valore ricevuto.

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

Successivamente, analizza le opzioni usando commandLineArgs() :

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

options ora assomigliano a questo:

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

Utilizzo avanzato

Oltre all'utilizzo tipico sopra descritto, è possibile configurare gli argomenti della riga di comando per accettare forme di sintassi più avanzate.

Sintassi basata su comando (stile git) nel modulo:

$ executable <command> [options]

Per esempio.

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

Sintassi dei comandi e dei sottocomandi (stile finestra mobile) nel modulo:

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

Per esempio.

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

Generazione guida di utilizzo

Una guida all'utilizzo (tipicamente stampata quando è impostata l' --help ) può essere generata utilizzando l'utilizzo della command-line-usage . Vedere gli esempi qui sotto e command-line-usage per le istruzioni su come crearli.

Un tipico esempio di guida all'utilizzo.

La guida all'uso di polymer-cli è un buon esempio di vita reale.

Ulteriori letture

C'è molto altro da imparare, per favore vedi il wiki per esempi e documentazione.




Commander.js

Funziona alla grande per la definizione di opzioni, azioni e argomenti. Genera anche le pagine di aiuto per te.

Promptly

Funziona alla grande per ricevere input dall'utente, se ti piace l'approccio di callback.

Co-Prompt

Funziona alla grande per ottenere input dall'utente, se ti piace l'approccio del generatore.




Probabilmente è una buona idea gestire la tua configurazione in modo centralizzato usando qualcosa come nconf https://github.com/flatiron/nconf

Ti aiuta a lavorare con i file di configurazione, le variabili di ambiente, gli argomenti della riga di comando.




Biblioteca Stdio

Il modo più semplice per analizzare gli argomenti della riga di comando in NodeJS è l'utilizzo del modulo stdio . Ispirato dall'utilità getopt UNIX, è così banale come segue:

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, mandatory: true},
    'ooo': {key: 'o'}
});

Se esegui il codice precedente con questo comando:

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

Quindi l'oggetto ops sarà il seguente:

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

Quindi puoi usarlo come vuoi. Per esempio:

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

Sono supportate anche le opzioni raggruppate, quindi puoi scrivere -om invece di -o -m .

Inoltre, stdio può generare automaticamente un output di aiuto / utilizzo. Se chiami ops.printHelp() otterrai quanto segue:

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

Il messaggio precedente viene mostrato anche se non viene fornita un'opzione obbligatoria (preceduta dal messaggio di errore) o se è stata specificata (ad esempio, se si specifica un singolo argomento per un'opzione e se ne richiede 2).

È possibile installare il modulo stdio utilizzando NPM :

npm install stdio



npm install ps-grab

Se vuoi eseguire qualcosa del genere:

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

-

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

O qualcosa come:

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

-

var grab=require('ps-grab');
grab('-OS') // return 'redhat'
grab('-VM') // return 'template-12332'



senza librairie: utilizzando Array.prototype.reduce ()

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

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

}, {})

per questo comando node index.js count=2 print debug=false msg=hi

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

anche,

possiamo cambiare

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

da (molto più a lungo)

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

per auto parse Boolean & Number

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



La maggior parte delle persone ha dato buone risposte. Vorrei anche contribuire con qualcosa qui. Sto fornendo la risposta usando la libreria lodash per scorrere tutti gli argomenti della riga di comando che passiamo mentre lodash l'app:

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

Per eseguire il codice sopra, esegui solo i seguenti comandi:

npm install
node index.js xyz abc 123 456

Il risultato sarà:

xyz 
abc 
123
456



Risposta del 2018 basata sulle tendenze attuali in natura:

Argomento dell'argomento di vanilla javascript:

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

Questo restituisce:

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

Documenti ufficiali

Pacchetti NPM più utilizzati per l'analisi degli argomenti:

Minimist : per l'analisi minima degli argomenti.

Commander.js : modulo più usato per l'analisi degli argomenti.

Meow : alternativa più leggera a Commander.js

Yargs : argomentazione più sofisticata dell'argomento (pesante).

Vorpal.js : applicazioni a linea di comando mature / interattive con analisi degli argomenti.




Senza librerie

Se vuoi farlo con vanilla JS / ES6 puoi usare la seguente soluzione

ha funzionato solo in 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;
  }, {});

E questo comando

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

produrrà il seguente risultato

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 Si prega di correggere il codice nella mappa e ridurre la funzione se si trova una soluzione più elegante, grazie;)




Un semplice frammento se ce n'è bisogno:

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