2014-04-26 15 views
11

Sto provando a scrivere uno script che accetterà come argomenti aggiuntivi sulla riga di comando una stringa vuota con virgolette doppie. Voglio che lo script trasmetta questi argomenti insieme alla stringa vuota doppia citata se è fornita, ma invece l'interprete dei comandi sembra interpretare tale argomento come una stringa vuota e rimuove le virgolette. C'è un modo per fare questo?Come si passa una stringa vuota con virgolette doppie a uno script bash?

Come semplice esempio avrei nel file script.sh:

#!/bin/bash 
/home/myapp $1 $2 

Se corro al prompt:

$ ./script.sh arg1 "" 

lo script viene eseguito solo "/home/myapp arg1" poco/ignora la secondo argomento (""). Voglio che preservare questa stringa vuota e invece eseguire: /home/myapp arg1 ""

risposta

3

È possibile rilevare il numero di parametri posizionali sono stati passati allo script da examining the $# parameter. Ad esempio, se questo è 2 o superiore, allora sai che è stato passato qualcosa per $2, anche se $2 è vuoto (le virgolette sono state rimosse chiamando shell).Quanto segue attua tale logica, e passa "" al programma richiamato (in questo caso echo) se il parametro è stato passato ma vuoto:

#!/bin/bash 

if [ $# -ge 2 ]; then 
    if [ "$2" ]; then 
     arg2="$2" 
    else 
     arg2='""' 
    fi 
    echo "$1 $arg2" 
elif [ $# == 1 ]; then 
    echo "$1" 
fi 

uscita:

 
$ ./args.sh a 
a 
$ ./args.sh a "" 
a "" 
$ ./args.sh a 1 
a 1 
$ 
+0

Perfetto, esattamente ciò di cui avevo bisogno Grazie! – Josh

+1

Impostare 'arg2 = '" "" 'sembrerà corretto quando lo fai eco, ma se provi ad usarlo per passare una stringa vuota a qualcos'altro (come in'/home/myapp $ 1 $ arg2'), ha vinto' t lavoro - passerà la stringa composta da due virgolette, non una stringa vuota. –

+0

@GordonDavisson * Voglio conservare questa stringa vuota ed eseguire invece: '/ home/myapp arg1" "' * Non è esattamente ciò che l'OP sta chiedendo? –

2

Si deve sfuggire utilizzando backslash

$ ./script.sh arg1 \"\" 

possono essere testati per esempio su eco:

$ echo \"\" 
"" 
+0

Grazie, sì, sono d'accordo che questo funziona, c'è qualche modo per non richiedere all'utente di sfuggire alle citazioni usando qualche magia script per rilevare che sono entrati una stringa come vuota e sostituire il comando con le virgolette? – Josh

+0

@Josh non è a conoscenza di alcuna magia del genere. Questa analisi viene eseguita dalla shell, quindi è necessario modificare la shell per applicare diverse regole di analisi. –

2
loro

fuggire con backslash o metterli tra virgolette singole.

2

È inoltre possibile inserirli in una singola virgola per ottenere i valori letterali, ad es. :

]$ echo '""' 
    "" 

Per esempio, in uno script:

]# cat a.bash 
    #!/bin/bash   
    echo a$1b 

    ]$ ./a.sh '""' 
    a""b 

    ]$ ./a.sh "" 
    ab 
3

Per completare Kaz's helpful explanation:
Se passaggio "[email protected]" attraverso, vuote argomenti saranno passati attraverso, anche:

#!/bin/bash 

/home/myapp "[email protected]" 

Passaggio a sud gh "[email protected]" conserva gli argomenti originali esattamente come passato in - anche argomenti passati come stringhe vuote (passati come, ad esempio, '' o "" o "$someVar", dove variabile someVar è posto o contiene una stringa vuota).


Nel caso in cui non ci può essere più di 2 argomenti:

#!/bin/bash 

# Copy the (up to) first 2 arguments - whether they're empty strings or not - 
# to a separate array. 
firstTwo=("${@:1:2}") 
shift; shift # Remove the first 2 arguments from the arguments array. 

# Invoke the app with the (up to) first 2 arguments stored in the new array. 
/home/myapp "${firstTwo[@]}" 

# Process the remaining arguments, if any. 
for a; do 
    echo "remaining: [$a]" 
done 
10

Hai correttamente passando una stringa vuota argomento alla sceneggiatura.

È lo script disordinarne:

#!/bin/bash 
/home/myapp $1 $2 

Lo script non protegge l'espansione di $1 e $2 da word-splitting. Ciò significa che se $1 e $2 contengono più parole, queste si trasformano in singoli argomenti, e se uno di essi si espande in nulla, semplicemente scompaiono.

Questo dovrebbe essere:

#!/bin/bash 
/home/myapp "$1" "$2" 

In generale, è possibile rendere il vostro script passare tutti i suoi argomenti per il programma invocato, in questo modo:

/home/myapp "[email protected]" 

le virgolette sono solo guscio sintassi; non fanno parte dei dati dell'argomento stesso. Quando si digita program "" nella shell, a livello di sistema operativo, il programma riceve una stringa di linguaggio C vuota: un puntatore a un byte null. Non ci sono citazioni.

È possibile passare l'argomento "" (una stringa di due caratteri composta da due virgolette) ma non è un argomento vuoto. Un modo per farlo è, ad esempio, '""': racchiuderlo tra virgolette singole.

L'unico motivo per fare cose del genere è quando si sta manipolando la sintassi della shell in un meta-livello: passando intorno pezzi di script di shell codice sorgente, come i token citati, vuoti o in altro modo. La shell ha un comando chiamato eval che accetta il codice sorgente come argomento (o più argomenti) e lo valuta.

empty_shell_string_syntax='""' # this variable holds the characters "" 

eval empty_var=$empty_shell_string_syntax # empty_var gets set to empty string 

prima che venga invocato il eval, la riga di comando è soggetta ad espansione. Quell'espansione rimuove la sintassi $empty_shell_string_sytnax e la sostituisce con il contenuto, i caratteri "". Quindi eval ottiene la stringa empty_var="". Valuta questo, e quindi empty_var è impostato sulla stringa vuota, come indica la sintassi.

+0

Hai ragione riguardo alla necessità di duplicare i riferimenti agli argomenti, ma se esprimi incondizionatamente '$ 2' (' "$ 2" '), sarà sempre _always_ passato come argomento (vuoto), anche se NO argomento del secondo era passato, che non è ciò che l'OP intendeva; '" $ @ "', al contrario, funziona come previsto; +1 per il resto della spiegazione. – mklement0

+1

È possibile aggirare il problema menzionando @ mklement0 utilizzando ad es. '/ home/myapp $ {1 +" $ 1 "} $ {2 +" $ 2 "}'. Questo è un po 'tortuoso, ma il modo in cui funziona è il costrutto '$ {var + something}' si espande a 'something' SE' $ var' è definito - quindi se '$ 2' non è definito,' $ {2 + "$ 2 "}' si espande a nulla e svanisce; se '$ 2' è definito (anche se è definito come la stringa vuota), si espande in' "$ 2" 'e le doppie virgolette lo proteggono dalla suddivisione in parole e dalla scomparsa se vuoto. –

0

Prova questo:

cmd=yourcomand; 
n=0; for a in "[email protected]"; do n=$((n +1)); cmd="$cmd \${$n+\"\$$n\"}"; done 
eval $cmd 
+1

Sebbene questo codice possa rispondere alla domanda, fornire un contesto aggiuntivo su come e/o perché risolve il problema migliorerebbe il valore a lungo termine della risposta. –

+0

Questo è basato sulla nota di Kaz e Gordon Davisson sopra, grazie. Si noti tuttavia che in generale l'espansione di $ {X + "$ X"} può produrre risultati indesiderati a seconda dei caratteri che contiene il valore valicabile. Quindi è meglio usare una sostituzione generale di tutte le variabili sulla riga di comando, solo dopo aver verificato che ci sia una stringa vuota presente. Dalle risposte di cui sopra non vedo ancora una soluzione generale. – alphasoup

Problemi correlati