Perché è possibile omettere gli spazi tra opzioni e parametri?


16

Per esempio:

xargs -n 1

equivale a

xargs -n1

Ma se guardi la pagina man , l'opzione è elencata come -n max-args, il che significa che lo spazio dovrebbe essere preservato. Non c'è nulla nella forma abbreviata -n max-args .

Questo succede anche con molte altre utility Linux.

Come si chiama questo in Linux? Tutte le utility supportano il modulo abbreviato (ma non lo documentano mai nella pagina man)?


1
12.1.2.a è parte della storia; Giuro che qui c'è già una buona domanda, ma non l'ho ancora trovata.

2
@drewbenn l'altra domanda a cui stai pensando potrebbe essere stata mia: unix.stackexchange.com/q/188046/41515

Risposte:


12

Quando si scrive il bit di analisi della riga di comando del codice, si specifica quali opzioni accettano argomenti e quali no. Ad esempio, in uno script shell che accetta -hun'opzione (per esempio aiuto) e -aun'opzione che dovrebbe accettare un argomento, lo fai

opt_h=0     # default value
opt_a=""

while getopts 'a:h' opt; do
    case $opt in
        h)  opt_h=1 ;;
        a)  opt_a="$OPTARG" ;;
    esac
done

echo "h: $opt_h"
echo "a: $opt_a"

Il a:hbit dice "Mi aspetto di analizzare due opzioni -ae -h, e -adovrei prendere un argomento" (è il :dopo ache dice al parser che -aaccetta un argomento).

Pertanto, non vi è mai alcuna ambiguità nel punto in cui un'opzione termina, dove inizia il suo valore e dove ne inizia un'altra.

Eseguendolo:

$ bash test.sh -h -a hello
h: 1
a: hello

$ bash test.sh -h -ahello
h: 1
a: hello

$ bash test.sh -hahello
h: 1
a: hello

Questo è il motivo per cui la maggior parte delle volte non dovresti scrivere il tuo parser della riga di comando per analizzare le opzioni.

C'è solo un caso in questo esempio che è complicato. L'analisi di solito si interrompe alla prima non opzione, quindi quando nella riga di comando sono presenti elementi che sembrano opzioni:

$ bash test.sh -a hello -world
test.sh: illegal option -- w
test.sh: illegal option -- o
test.sh: illegal option -- r
test.sh: illegal option -- l
test.sh: illegal option -- d
h: 0
a: hello

Quanto segue risolve che:

$ bash test.sh -a hello -- -world
h: 0
a: hello

Il --segnale -worldindica la fine delle opzioni della riga di comando e il bit viene lasciato al programma per fare quello che vuole (è in una delle variabili posizionali).

Questo è, tra l'altro, il modo in cui rimuovi un file che ha un trattino all'inizio del suo nome rm.

MODIFICA :

Utilità scritte in C call getopt()(dichiarate in unistd.h) che funzionano più o meno allo stesso modo. In effetti, per quanto ne sappiamo, la bashfunzione di getoptspuò essere implementato usando una chiamata alla funzione di libreria C getopt(). Perl, Python e altri linguaggi hanno librerie di analisi della riga di comando simili ed è molto probabile che eseguano l'analisi in modi simili.

Alcune di queste getopte getoptsimili routine di libreria gestiscono anche opzioni "lunghe". Questi sono generalmente preceduti da double-dash ( --), e le opzioni lunghe che accettano argomenti spesso lo fanno dopo un segno di uguale, ad esempio l' --block-size=SIZEopzione di [alcune implementazioni] dudell'utilità (che consente anche -B SIZEdi specificare la stessa cosa).

Il motivo per cui i manuali sono spesso scritti per mostrare uno spazio tra le opzioni brevi e i loro argomenti è probabilmente per la leggibilità.

EDIT : strumenti davvero vecchi, come i programmi di utilità dde tar, hanno opzioni senza trattini davanti a loro. Questo è puramente per ragioni storiche e per mantenere la compatibilità con i software che si affidano a loro per funzionare esattamente in quel modo. L' tarutilità ha acquisito la capacità di prendere opzioni con trattini in tempi più recenti. Il manuale BSD per tarchiama le opzioni vecchio stile per "flag raggruppati".


Questa funzionalità può sembrare facile da implementare negli script bash. Ma penso che la maggior parte dei programmi di utilità siano scritti in C (quindi compilati in binari) e non bash. Perché queste utility implementano questa funzione?
J.Joe,

@ J.Joe Perché chiamano getopt()(dichiarato in unistd.h), che fa la stessa cosa.
Kusalananda

2
Sì, hai ragione. Riferimento . Questo risolve anche un altro mistero che le opzioni possono essere combinate -a -b=== -ab
J.Joe il

1
Gli argomenti opzionali per i flag creerebbero un'ambiguità, quindi non possono essere combinati (se -aha un argomento opzionale, -abnon è lo stesso di -a -b). GNU getopt non interrompe l'elaborazione dei flag quando incontra un non-flag: invece (per impostazione predefinita), invece rimescola i flag in primo piano in argv.
Ilkkachu,

@ilkkachu Grazie per questo chiarimento. Potrei aggiornare la mia risposta in seguito.
Kusalananda

4

xargsè una delle utility POSIX. Come commentato da @drewbenn, POSIX documenta il comportamento dell'analisi delle opzioni per la maggior parte delle sue utilità da abbinare getopt, con alcune quote per altre implementazioni, dicendo in 12.1 Sintassi dell'argomento Utility :

Questa sezione descrive la sintassi degli argomenti delle utility standard e introduce la terminologia utilizzata in POSIX.1-2008 per descrivere gli argomenti elaborati dalle utility.

All'interno di POSIX.1-2008, viene utilizzata una notazione speciale per descrivere la sintassi degli argomenti di un'utilità. Se non diversamente indicato , tutte le descrizioni delle utility utilizzano questa notazione, che è illustrata da questo esempio (vedere Comandi semplici XCU ):

e concludendo con

Si consiglia a tutte le utility e applicazioni future di utilizzare queste linee guida per migliorare la portabilità dell'utente. Il fatto che alcune utility storiche non possano essere modificate (per evitare di rompere le applicazioni esistenti) non dovrebbe scoraggiare questo obiettivo futuro.

All'interno di POSIX (ricorda che copre solo le utility più comunemente usate), ci sono eccezioni che passano operandi che sarebbero opzioni in altre utility come parametri posizionali o parametri con sintassi speciale :

POSIX consente valori opzionali opzionali:

Gli argomenti opzione sono mostrati separati dalle loro opzioni da <blank>caratteri, tranne quando l'argomento opzione è racchiuso nella notazione '['e ']'per indicare che è facoltativo.

Di rado, non ricordo quali utility POSIX utilizzano la funzione. I ncurses tice infocmputilità utilizza la funzionalità per i livelli di -vopzione (verbose / debug).

Il punto specifico di cui hai chiesto è dettagliato nel resto di quel paragrafo, andando su più righe.

Prima di POSIX, alcune implementazioni di psopzioni accettate senza un trattino iniziale. La descrizione POSIX non menziona questo nella descrizione dell'utilità o nella logica della sintassi:

Oltre a POSIX, ci sono implementazioni di opzioni lunghe (come GNU getopt_long o X Toolkit ), che usano una varietà di modi per separare o unire il valore di un'opzione all'opzione. Ad esempio, la punteggiatura può essere utilizzata:

--option=value
--option value

A seconda dell'implementazione, un doppio trattino può / non può essere usato per distinguere le opzioni lunghe da corte (getopt): lynx e X Toolkit usano un singolo trattino; GNU getopt_longusa un doppio trattino, per esempio. Inoltre, a +può essere usato per indicare che un'opzione è negata.

La descrizione di POSIX non sembra menzionare nessuno di questi, ma è probabile che li incontrerai.


È -option=valuedovrebbe essere --option=value(il formato lungo opzione, due trattini in principio, invece di uno)?
J.Joe

Alcune utility legacy utilizzano opzioni lunghe a trattino singolo (-option) ma sono ampiamente deprecate per nuovi script e programmi. Utilizzare un trattino singolo per le opzioni brevi gestite da getopt. Quasi tutti i nuovi script e programmi utilizzano opzioni lunghe a doppio trattino. Molti supportano anche equivalenti di opzioni brevi a trattino singolo per quelli più comunemente usati. Le lunghe opzioni rendono il codice di script molto più autocompattante, richiedendo meno commenti.
DocSalvager,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.