2011-10-06 12 views

risposta

49

Il read nel comando di script va bene. Tuttavia, lo si esegue nella pipeline, il che significa che si trova in una subshell, pertanto le variabili che legge non sono visibili nella shell principale. È possibile

  • spostare il resto dello script nella subshell, troppo:

    echo hello | { read str 
        echo $str 
    } 
    
  • o utilizzare sostituzione di comando per ottenere il valore della variabile di subshell

    str=$(echo hello) 
    echo $str 
    

    o un esempio un po 'più complicato (afferrando il 2 ° elemento di ls)

    str=$(ls | { read a; read a; echo $a; }) 
    echo $str 
    
+0

Esempi impressionanti! Ho dovuto modificarlo leggermente su OSX inserendo spazi all'interno delle parentesi graffe e un punto e virgola dopo l'eco, in questo modo: str = $ (ls | {leggi a; leggi a; echo $ a;}) –

+5

Perché è "leggi a; leggi a;" richiesto * due volte *? – javadba

+0

@javadba: non è necessario due volte. L'esempio fornito restituisce * second * item da 'ls'. Con un singolo 'read a' otterresti il ​​primo oggetto. Non chiedermi perché l'addetto alla risposta ha scelto questo esempio. – Fritz

3

Il valore scompare dal momento che il comando di lettura viene eseguito in una subshell separata: Bash FAQ 24

-5

Avete bisogno del tubo?

echo -ne "$MENU" 
read NUMBER 
+1

-1: i comandi 'echo' e' read' non sono collegati in alcun modo. –

+0

È così male? Funziona ... – mmrtnt

+0

Il poster vuole chiaramente un modo automatico per popolare una variabile senza doverla inserire manualmente. –

33

Altre alternative bash che non comportano una subshell:

read str <<END    # here-doc 
hello 
END 

read str <<< "hello"  # here-string 

read str < <(echo hello) # process substitution 
+2

Puoi anche usare un processo per la stringa here come 'leggere ABC <<< $ (echo 'aaa bbb ccc')' – maxpolk

8

uso tipico potrebbe essere simile:

i=0 
echo -e "hello1\nhello2\nhello3" | while read str ; do 
    echo "$((++i)): $str" 
done 

e l'uscita

1: hello1 
2: hello2 
3: hello3 
2

Per mettere i miei due centesimi qui: su KSH, read zione come è ad una variabile sarà lavoro, perché secondo the IBM AIX documentation, di KSH readfa influenza di shell corrente:

L'impostazione di variabili shell dal comando di lettura influenza l'ambiente di esecuzione shell corrente.

Questo solo ha provocato in me spendendo pochi minuti buoni per capire il motivo per cui una battuta che termina con read che ho usato un'infinità di volte prima su AIX non ha funzionato su Linux ... è perché KSH fa salva l'ambiente corrente e BASH no!

0

Un'altra alternativa è l'uso della funzione printf.

printf -v str 'hello' 

Inoltre, questo costrutto, combinato con l'uso di singoli apici eventualmente aiuta ad evitare i problemi multi-fuga di subshells e altre forme di interpolativo citare.

+0

Se è tutto ciò che stai cercando di ottenere, potresti anche fare 'str = ' hello'. Penso che il punto qui sia quello di catturare l'output di un comando in una variabile. – mc0e

0

ho davvero solo per uso letto con "mentre" e un ciclo fare:

echo "This is NOT a test." | while read -r a b c theRest; do 
echo "$a" "$b" "$theRest"; done 

Questa è una prova.
Per quello che vale, ho visto la raccomandazione di usare sempre -r con il comando di lettura in bash.

Problemi correlati