Come faccio a sfuggire al carattere jolly / asterisco in bash?

per esempio.

me$ FOO="BAR * BAR" me$ echo $FOO BAR file1 file2 file3 file4 BAR 

e usando il carattere di escape “\”:

 me$ FOO="BAR \* BAR" me$ echo $FOO BAR \* BAR 

Sto ovviamente facendo qualcosa di stupido.

Come ottengo l’uscita “BAR * BAR”?

    Citando quando si imposta $ FOO non è abbastanza. È necessario citare anche il riferimento alla variabile:

     me$ FOO="BAR * BAR" me$ echo "$FOO" BAR * BAR 

    RISPOSTA BREVE

    Come altri hanno già detto, dovresti sempre citare le variabili per evitare comportamenti strani. Quindi usa echo “$ pippo” invece di echo $ pippo .

    RISPOSTA LUNGA

    Penso che questo esempio meriti ulteriori spiegazioni perché c’è molto di più di quanto possa sembrare a prima vista.

    Posso vedere da dove viene la tua confusione perché dopo aver eseguito il tuo primo esempio probabilmente hai pensato a te stesso che la shell stava ovviamente facendo:

    1. Espansione dei parametri
    2. Espansione del nome file

    Quindi dal tuo primo esempio:

     me$ FOO="BAR * BAR" me$ echo $FOO 

    Dopo l’espansione dei parametri è equivalente a:

     me$ echo BAR * BAR 

    E dopo l’espansione del nome file è equivalente a:

     me$ echo BAR file1 file2 file3 file4 BAR 

    E se scrivi semplicemente echo BAR * BAR nella riga di comando, vedrai che sono equivalenti.

    Quindi probabilmente hai pensato a te stesso “se riesco a sfuggire a *, posso impedire l’espansione del nome file”

    Quindi dal tuo secondo esempio:

     me$ FOO="BAR \* BAR" me$ echo $FOO 

    Dopo l’espansione dei parametri dovrebbe essere equivalente a:

     me$ echo BAR \* BAR 

    E dopo l’espansione del nome file dovrebbe essere equivalente a:

     me$ echo BAR \* BAR 

    E se provate a digitare “echo BAR \ * BAR” direttamente nella riga di comando, stamperà effettivamente “BAR * BAR” perché l’espansione del nome file viene impedita dall’esecuzione.

    Quindi perché usare $ foo non funziona?

    È perché c’è una terza espansione che si svolge – Citazione rimozione. Dalla rimozione del preventivo manuale di bash è:

    Dopo le espansioni precedenti, tutte le occorrenze non quotate dei caratteri ‘\’, ” ” e ‘”‘ che non risultano da una delle espansioni di cui sopra vengono rimosse.

    Quindi, quando si digita il comando direttamente nella riga di comando, il carattere di escape non è il risultato di un’espansione precedente, quindi BASH lo rimuove prima di inviarlo al comando echo, ma nel secondo esempio, “\ *” era il risultato di una precedente espansione del parametro, quindi NON viene rimosso. Di conseguenza, echo riceve “\ *” e questo è ciò che stampa.

    Notare la differenza tra il primo esempio – “*” non è incluso nei caratteri che verranno rimossi da Rimozione Quote.

    Spero che abbia senso. Alla fine la conclusione nello stesso – basta usare le virgolette. Ho solo pensato di spiegare perché l’escape, che logicamente dovrebbe funzionare se solo l’espansione di Parameter e Filename è in gioco, non ha funzionato.

    Per una spiegazione completa delle espansioni di BASH, fare riferimento a:

    http://www.gnu.org/software/bash/manual/bashref.html#Shell-Expansions

    Aggiungerò un po ‘a questo vecchio thread.

    Solitamente useresti

     $ echo "$FOO" 

    Tuttavia, ho avuto problemi anche con questa syntax. Considera il seguente script.

     #!/bin/bash curl_opts="-s --noproxy * -O" curl $curl_opts "$1" 

    Il * deve essere passato letteralmente per curl , ma gli stessi problemi sorgeranno. L’esempio sopra non funzionerà (si espanderà nei nomi di file nella directory corrente) e neanche \* . Non puoi inoltre citare $curl_opts perché verrà riconosciuto come una singola opzione (non valida) da curl .

     curl: option -s --noproxy * -O: is unknown curl: try 'curl --help' or 'curl --manual' for more information 

    Quindi raccomanderei l’uso della variabile bash $GLOBIGNORE per evitare del tutto l’espansione del nome del file se applicata al pattern globale, o usare il flag set -f incorporato.

     #!/bin/bash GLOBIGNORE="*" curl_opts="-s --noproxy * -O" curl $curl_opts "$1" ## no filename expansion 

    Applicando al tuo esempio originale:

     me$ FOO="BAR * BAR" me$ echo $FOO BAR file1 file2 file3 file4 BAR me$ set -f me$ echo $FOO BAR * BAR me$ set +f me$ GLOBIGNORE=* me$ echo $FOO BAR * BAR 
     FOO='BAR * BAR' echo "$FOO" 
     echo "$FOO" 

    Può valere la pena prendere l’abitudine di usare printf piuttosto che echo sulla riga di comando.

    In questo esempio non offre molti vantaggi ma può essere più utile con un output più complesso.

     FOO="BAR * BAR" printf %s "$FOO"