2013-10-03 10 views
22

OK, Quindi PHP ha una funzione integrata getopt() che restituisce informazioni su quali opzioni del programma l'utente ha fornito. Solo, a meno che mi manchi qualcosa, è completamente rotto! Dal manuale:Dopo aver usato getopt() di PHP, come posso dire quali argomenti rimangono?

L'analisi delle opzioni termina alla prima non opzione trovata, tutto ciò che segue viene scartato.

Così getopt() restituisce un array con il valido e analizzato solo opzioni. È ancora possibile vedere l'intera riga di comando originale guardando a , che rimane invariato, ma come si dice a dove nella riga di comando getopt() interrompe l'analisi degli argomenti? È essenziale sapere questo se si desidera trattare il resto di una riga di comando come altre cose (come, ad esempio, i nomi dei file).

Ecco un esempio ...

Supponiamo che io voglio creare uno script per accettare i seguenti argomenti:

Usage: test [OPTION]... [FILE]... 

Options: 
    -a something 
    -b something 
    -c something 

allora potrei chiamare getopt() come questo:

$args = getopt('abc'); 

E, se ho eseguito la sceneggiatura in questo modo:

$ ./test.php -a -bccc file1 file2 file3 

dovrei aspettare di avere la seguente matrice restituita a me:

Array 
(
    [a] => 
    [b] => 
    [c] => Array 
     (
      [0] => 
      [1] => 
      [2] => 
     ) 
) 

Quindi la domanda è questa: come sulla Terra faccio a sapere che i tre non analizzata, non sia un'opzione FILE argomentazioni partono da $argv[ 3 ]? ??

+1

Si potrebbe guardare in Console_GetOpt (http://stackoverflow.com/questions/1023095/phps-command-line-option-parsing-howto) ma richiede PEAR. – andig

+0

Hai specificato il file come ultimo parametro in modo da poter eseguire '$ argv [count ($ argv) - 1]' – EaterOfCode

+2

@EaterOfCode: non è sufficiente. È possibile specificare qualsiasi numero di file, quindi è necessario sapere quanti argomenti non-opzione non analizzati ci sono alla fine. – edam

risposta

2

Nessuno ha detto che tu hai bisogno di getopt. Puoi farlo nel modo che preferisci:

$arg_a = null; // -a=YOUR_OPTION_A_VALUE 
$arg_b = null; // -b=YOUR_OPTION_A_VALUE 
$arg_c = null; // -c=YOUR_OPTION_A_VALUE 

$arg_file = null; // -file=YOUR_OPTION_FILE_VALUE 

foreach ($argv as $arg) 
{ 
    unset($matches); 

    if (preg_match('/^-a=(.*)$/', $arg, $matches)) 
    { 
     $arg_a = $matches[1]; 
    } 
    else if (preg_match('/^-b=(.*)$/', $arg, $matches)) 
    { 
     $arg_b = $matches[1]; 
    } 
    else if (preg_match('/^-c=(.*)$/', $arg, $matches)) 
    { 
     $arg_c = $matches[1]; 
    } 
    else if (preg_match('/^-file=(.*)$/', $arg, $matches)) 
    { 
     $arg_file = $matches[1]; 
    } 
    else 
    { 
     // all the unrecognized stuff 
    } 
}//foreach 

if ($arg_a === null) { /* missing a - do sth here */ } 
if ($arg_b === null) { /* missing b - do sth here */ } 
if ($arg_c === null) { /* missing c - do sth here */ } 
if ($arg_file === null) { /* missing file - do sth here */ } 

echo "a=[$arg_a]\n"; 
echo "b=[$arg_b]\n"; 
echo "c=[$arg_c]\n"; 
echo "file=[$arg_file]\n"; 

Lo faccio sempre così e funziona. Inoltre posso fare tutto ciò che voglio con esso.

+2

Sì, ma preferirei poter usare la libreria integrata, invece di usare il mio uno in giro con me ovunque. Questo mi sembra un difetto grave nella libreria integrata, per me. (Inoltre, il tuo codice di esempio non gestirà, ad esempio, il parametro della riga di comando '-bccc' nel mio esempio. Sono sicuro che ci sono più completi esempi di parser da riga di comando per PHP, ma questo tipo di sconfigge il punto di questa domanda!) – edam

+0

Basta usare 'strtok' e foreach i risultati saranno migliori. – Gasol

+1

Mi sono imbattuto in diverse situazioni in cui le funzioni integrate di PHP mancano un po 'il segno e ho avuto bisogno di costruirmi una mia. Non penso che questo dovrebbe essere downvoted perché sta cercando creativamente di risolvere il problema che la funzione incorporata di PHP non risponde. Non è una risposta perfetta, ma non è una schifosa. – n0nag0n

2

È possibile utilizzare quanto segue per ottenere gli argomenti che seguono le opzioni della riga di comando. Può essere usato prima o dopo il richiamo di PHP di getopt() con nessun cambiamento nel risultato:

# $options = getopt('cdeh'); 

$argx = 0; 

while (++$argx < $argc && preg_match('/^-/', $argv[$argx])); # (no loop body) 

$arguments = array_slice($argv, $argx); 

$arguments ora contiene tutti gli argomenti seguenti tutte le opzioni principali. In alternativa, se non si desidera l'argomento/gli argomenti in un array separato, allora $argx è l'indice del primo argomento effettivo: $argv[$argx].

Se non ci sono argomenti, dopo eventuali opzioni principali, quindi:

  • $arguments è un array vuoto [] e
  • count($arguments) == 0 e
  • $argx == $argc.
+0

Questa è una risposta terribile! Ignora tutti gli argomenti della riga di comando che iniziano con un '-' e presuppone che il resto siano argomenti non opzionali! Cosa succede se eseguo una riga di comando questo: './example --name Bob -s 23'? Qui posso avere * no * argomenti non-option (se --name e -s accettano entrambi un argomento di opzione), e il tuo codice direbbe che '[" Bob "," -s "," 23 "]' non erano -opzioni di opzione. Il problema è che * fino a * non analizzi le opzioni, * non puoi dire * quali argomenti sono argomenti non opzionali. 'Getopt()' di PHP dovrebbe indicare quali argomenti non fanno parte di un'opzione, in qualche modo. E non è così. – edam

0

Dai un'occhiata a GetOptionKit per sbarazzarti dell'analisi della bandiera.

http://github.com/c9s/GetOptionKit

GetOptionKit può essere facilmente integrato nello script da riga di comando. Supporta il vincolo di tipo, la validazione del valore e così via.

+0

Grazie. Sono consapevole che ci sono altre librerie per fare questo. Mi sono chiesto se c'è un modo per farlo con la funzione nativa 'getopt()' di PHP. Sembra che non ci sia. – edam

3

A partire da PHP 7.1, getopt supporta un parametro facoltativo by-ref, &$optind, che contiene l'indice in cui l'analisi dell'argomento si interrompe. Questo è utile per mescolare i flag con argomenti posizionali. Es .:

[email protected]:~$ php -r '$i = 0; getopt("a:b:", [], $i); print_r(array_slice($argv, $i));' -- -a 1 -b 2 hello1 hello2 
Array 
(
    [0] => hello1 
    [1] => hello2 
) 
Problemi correlati