Domanda

ad es.

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

e usando " \ " carattere di escape:

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

Ovviamente sto facendo qualcosa di stupido.

Come posso ottenere l'output " BAR * BAR " ?

È stato utile?

Soluzione

Citare quando si imposta $ FOO non è sufficiente. Devi citare anche il riferimento alla variabile:

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

Altri suggerimenti

RISPOSTA CORTA

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

RISPOSTA LUNGA

Penso che questo esempio meriti ulteriori spiegazioni perché c'è molto di più di quello che potrebbe sembrare in faccia.

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 ovviamente sta facendo:

  1. Espansione dei parametri
  2. Espansione 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 del file è equivalente a:

me$ echo BAR file1 file2 file3 file4 BAR

E se digiti echo BAR * BAR nella riga di comando vedrai che sono equivalenti.

Quindi probabilmente hai pensato a te stesso '' Se sfuggo al *, 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:

<*>

E se provi a digitare " echo BAR \ * BAR " direttamente nella riga di comando verrà effettivamente stampato "BAR * BAR" perché l'espansione del nome file è impedita dall'escape.

Quindi perché usare $ foo non ha funzionato?

È perché c'è una terza espansione che ha luogo: la rimozione delle quotazioni. Dalla rimozione manuale del preventivo bash è:

  

Dopo le precedenti espansioni, tutto   ricorrenze non quotate dei personaggi   "\", "" E """ che non hanno prodotto risultati   da una delle espansioni di cui sopra sono   rimosso.

Quindi ciò che accade è quando si digita il comando direttamente nella riga di comando, il carattere di escape non è il risultato di una precedente espansione, quindi BASH lo rimuove prima di inviarlo al comando echo, ma nel secondo esempio, il " \ * " era il risultato di una precedente espansione dei parametri, quindi NON è stato rimosso. Di conseguenza, l'eco riceve " \ * " ed è quello che stampa.

Nota la differenza tra il primo esempio - " * " non è incluso nei caratteri che verranno rimossi dalla Rimozione preventivo.

Spero che abbia senso. Alla fine la conclusione è la stessa: basta usare le virgolette. Ho solo pensato di spiegare perché l'escaping, che logicamente dovrebbe funzionare se sono in gioco solo le espansioni di Parameter e Filename, non ha funzionato.

Per una spiegazione completa delle espansioni BASH, consultare:

http://www.gnu.org/software/ bash / manuale / bashref.html # Shell-Espansioni

Aggiungerò un po 'a questo vecchio thread.

Di solito useresti

$ echo "$FOO"

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

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

* deve essere passato letteralmente a curl , ma sorgeranno gli stessi problemi. L'esempio sopra non funzionerà (si espanderà ai nomi di file nella directory corrente) e nemmeno \ * . Inoltre non puoi citare $ curl_opts perché sarà riconosciuto come una singola opzione (non valida) per curl .

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

Pertanto, raccomanderei l'uso della variabile bash $ GLOBIGNORE per impedire del tutto l'espansione del nome file se applicato al modello globale, oppure usare set -f bandiera integrata.

#!/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"

Potrebbe valere la pena prendere l'abitudine di usare printf anziché echo sulla riga di comando.

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

FOO="BAR * BAR"
printf %s "$FOO"
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top