2013-04-13 18 views
5

ho bisogno per concatenare più stringhe in loop e assegnare il risultato alla variabile:Come per concatenare le stringhe formattate con printf in bash

esempio stringa formattata:

result=$(printf '| %-15s| %-25s| %-15s| %-15s| %-15s\n' $size $name $visits $inbound $outbound); 

Dal mio punto di vista dovrebbe funzionare in questo modo:

result='' 
while read somevar 
do 
    ... 
    outbound=`cat "$www_path/$name/access.log"|grep \`date +"%d/%b/%Y"\`|awk '{ sum+=$11} END {print sum/1024/1024}'` 
    result=$(printf '%s| %-15s| %-25s| %-15s| %-15s| %-15s\n' $result $size $name $visits $inbound $outbound); 
    ... 
done 
echo $result 

Ma non :(

UPD:

codice completo elenco qui sotto:

www_path='/var/www'; 
result=''; 
cd /var/www/; ls -d */ | while read i ; do basename "$i" ; done 
while read i; 
do du -sh "$i"| 
     while read size name 
     do 
       visits=`cat "$www_path/$name/access.log"|grep \`date +"%d/%b/%Y"\`|grep -v "internal dummy connection"|awk -F ' ' '{print $1}' | sort | uniq | wc -l|tr '\n' '\t'|sed 's/$/\t/'` 
       inbound=`cat "$www_path/$name/access.log"|grep \`date +"%d/%b/%Y"\`|grep -v "internal dummy connection"|awk '{ sum+=$10} END {print sum/1024/1024}'|tr '\n' '\t'|sed 's/$/\t\t/'` 
       outbound=`cat "$www_path/$name/access.log"|grep \`date +"%d/%b/%Y"\`|grep -v "internal dummy connection"|awk '{ sum+=$11} END {print sum/1024/1024}'`; 
       result=$(printf '%s| %-15s| %-25s| %-15s| %-15s| %-15s\n' "$result" "$size" "$name" "$visits" "$inbound" "$outbound") 
     done 
done 
echo $result 
+3

** Sempre ** assicurarsi che il codice inserito in una domanda riproduca il problema riscontrato; il tuo post originale no. Il motivo 'result' è vuoto è che ti stai assegnando all'interno di una subshell; quelle modifiche scompaiono dopo la chiusura della subshell. Non c'era modo per noi di sapere questo in base alla tua domanda originale. – chepner

+1

Su un'altra nota - questo è un codice incredibilmente terribile. Non si dovrebbe mai analizzare l'output da 'ls' in questo modo; vedi http://mywiki.wooledge.org/ParsingLs per una spiegazione del perché - anche, facendo 'cat | grep' tre volte per ogni singola riga di input è estremamente inefficiente. –

risposta

7

Utilizzare i doppi apici intorno risultato $ e tutte le altre variabili che possono contenere spazi e altri caratteri speciali se devono essere utilizzati come un unico argomento di un programma o funzione built-in:

result=$(printf '%s| %-15s| %-25s| %-15s| %-15s| %-15s\n' "$result" "$size" "$name" "$visits" "$inbound" "$outbound") 

Se desidera solo per assegnare il risultato di printf ad una variabile (come avete fatto), è anche possibile utilizzare

printf -v result '%s| %-15s| %-25s| %-15s| %-15s| %-15s\n' "$result" "$size" "$name" "$visits" "$inbound" "$outbound" 

BTW: c'è anche un + = operatore di assegnamento che aggiunge solo per le stringhe (vedere pagina man di bash, parametri della sezione).

Nella lista completa del codice, manca un segno di tubo dopo il 'done' prima del secondo 'while read i'.

E quando si chiama

echo $result 

il contenuto del risultato $ è già persa, dal momento che la printf è chiamato in un processo sub creato dal segno tubo dopo 'fare du ...'. I processi parent non hanno accesso alle variabili (ambiente) del processo secondario.

Preferirei riscrivere il codice a qualcosa come

result="" 
for name in /var/www/* ; do 
    read size __ < <(du -sh "$name") 
    name=${name##*/} 
    #insert the other stuff here and add arguments to printf 
    printf -v line '| %-15s| %-25s\n' "$size" "$name" 
    result+=$line 
done 
echo "$result" 

Il read < <(cmd) espressione è simile a cmd | read ma il primo mette il comando nel processo di sub, invece, mentre la lettura viene eseguita nel processo principale. In questo modo, le variabili impostate da read possono essere utilizzate anche nei comandi successivi.

+0

sembra che il problema non sia in printf ma da qualche parte in pipe e loop. ho aggiunto il codice sorgente completo – user947668

+0

Ho aggiornato la risposta, la cosa principale è probabilmente l'accesso al risultato env var dal processo padre più in alto – Jacob

+0

Jacob, grazie. Il tuo codice è molto meglio! – user947668

1

il codice sia OK. Una cosa che devi fare, dal momento che result conterrà spazi vuoti quando si aggiungono ad essa, è citare la sua espansione:

result=$(printf '...' "$result" "$size" "$name" ...) 

Citando le altre variabili potrebbe non essere necessario, ma di solito è una buona idea.

La mancata citazione di $result non dovrebbe tuttavia causare la completa oscurità. Potrebbe essere necessario inserire altro codice nel ciclo while.

+0

ho aggiunto un esempio di variabile $ in uscita. altre variabili utilizzate in printf sono simili. non c'è nient'altro nel ciclo completo codice sorgente – user947668

+0

aggiunto. – user947668