2013-04-13 17 views
5

I trzeba złączyć kilka napisów w pętlę i przypisać wynik do zmiennej:Jak łączenia ciągów sformatowane printf w bash

sformatowany przykład wyrażenie:

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

Z moim zdaniem to powinno działać tak:

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 

Ale to nie ma :(

UPD:

Pełny wykaz poniżej kod:

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

** Zawsze ** upewnij się, że kod wpisany w pytaniu odtwarza problem, który masz; Twój oryginalny wpis nie. Powód 'wynik' jest pusty jest taki, że przypisujesz go wewnątrz podpowłoki; te zmiany znikną po zamknięciu podpowłoki. Nie mogliśmy tego poznać na podstawie twojego pierwotnego pytania. – chepner

+1

Inna uwaga - to zdumiewająco okropny kod. Nigdy nie powinieneś parsować wyjścia z 'ls' w ten sposób; zobacz http://mywiki.wooledge.org/ParsingLs dla wyjaśnienia, dlaczego - także, wykonując 'cat | grep' trzy razy dla każdej linii wejściowej jest wyjątkowo nieefektywna. –

Odpowiedz

7

użyć cudzysłowów około $ wynik i wszystkie inne zmienne, które mogą zawierać spacje i inne znaki specjalne, jeśli mają być używane jako pojedynczy argument do programu lub wbudowaną funkcję:

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

Jeśli po prostu chcesz przypisać wynik printf do zmiennej (jak ty), można również użyć

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

BTW: tam również a + = operator przypisania że właśnie dołącza do strun (patrz strona bash człowiek, parametry rozdział).

W pełnym kodzie brak znaku potoku po "zakończeniu" przed drugim "while read i".

A kiedy zadzwonić

echo $result 

zawartość $ result jest już stracone, ponieważ printf jest nazywany w procesie sub utworzonego przez rury po znaku „zrobić du ...”. Procesy nadrzędne nie mają dostępu do zmiennych (środowiska) podprocesu.

Wolę przepisać kod z czymś jak

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" 

Wyrażenie read < <(cmd) jest podobny do cmd | read ale były stawia komendy w procesie sub zamiast, a odczyt jest wykonywany w głównym procesie. W ten sposób zmienne ustawione przez odczyt mogą być użyte również w kolejnych poleceniach.

+0

Wygląda na to, że problem nie występuje w printf, ale gdzieś w rurach i pętlach. Dodałem pełny kod źródłowy – user947668

+0

Zaktualizowałem odpowiedź, najważniejszą rzeczą jest prawdopodobnie dostęp do wyniku env var od najwyższego procesu nadrzędnego – Jacob

+0

Jacob, dziękuję. Twój kod jest znacznie lepszy! – user947668

1

Twój kod wygląda OK. Jedną rzeczą, którą trzeba zrobić, ponieważ result będzie zawierać spacje w miarę dodawania do niego, to zacytować ekspansję:

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

powołując się na inne zmienne nie mogą być konieczne, ale zazwyczaj jest to dobry pomysł.

Nie powiem jednak, że podanie wartości $result jest całkowicie puste. Może być konieczne opublikowanie większej ilości kodu w pętli while.

+0

Dodałem przykład zmiennej wychodzącej $. inne zmienne używane w printf są podobne. nie ma nic więcej w pętli – user947668

+0

pełny kod źródłowy został dodany. – user947668