2013-04-13 4 views
5

bashでのprintfでフォーマット文字列を連結する方法:私はループ内で複数の文字列を連結し、結果を変数に割り当てる必要が

フォーマットされた文字列の例:私の見解から

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

それは次のように動作するはずです:

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 

しかし、それはしません:(

UPD:以下のリスト

全コード:

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

**常に**あなたが質問に投稿したコードがあなたの問題を再現していることを確認してください。あなたの元の投稿はしませんでした。 'result'が空である理由は、あなたがサブシェルの中でそれに割り当てていることです。これらの変更は、サブシェルが終了すると消えます。元の質問に基づいてこれを知る方法はありませんでした。 – chepner

+1

もう一つの注意点 - これは驚くほど恐ろしいコードです。このようにして 'ls'の出力を解析するべきではありません。その理由の説明については、http://mywiki.wooledge.org/ParsingLsを参照してください。また、 'cat |入力の1行ごとに3回grepが非常に非効率的です。 –

答えて

7

使用$結果二重引用符で囲むと、彼らはプログラムに1つの引数として使用したり、内蔵機能することになっている場合は空白やその他の特殊文字が含まれていてもよい他のすべての変数:

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

あなたの場合ただ変数にprintf関数の結果を割り当てる(あなたが行ったように)、あなたはまたところで

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

を使用することができます。そこにも文字列だけで(bashのmanページを参照してください、セクションパラメータに追加+ =代入演算子は、 )。

完全コードリストでは、2番目の 'read i'の前に 'done'の後にパイプ記号がありません。

そして、あなたは

echo $result 

を呼び出すときのprintfは、後にパイプ記号によって作成されたサブプロセスで呼び出されるので、$結果の内容はすでに、失われた「を実行デュ...」。親プロセスは、サブプロセスの(環境)変数にアクセスできません。読み出しがメインプロセスで実行されている間

私はむしろ、

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" 

read < <(cmd)式はcmd | readに似ているが、前者は代わりにサブプロセスにコマンドを置くようなものにコードを書き換えると思います。このようにして、readで設定された変数は後続のコマンドでも使用できます。

+0

問題はprintfではなくパイプやループのどこかにあるようです。私は完全なソースコードを追加しました – user947668

+0

私は答えを更新しました、主なものはおそらくトップの親プロセスからの結果のenv varへのアクセスです – Jacob

+0

Jacob、ありがとう。あなたのコードははるかに優れています! – user947668

1

あなたのコードはOKになります。あなたはそれに追加するようresultが空白文字が含まれていますので、あなたはその拡大を引用され、何をする必要があります一つのこと:

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

は、他の変数を引用は必要ではないかもしれないが、それは通常は良いアイデアです。

$resultを引用符で囲まないと完全に空白にならないはずです。ループのwhileループにコードを投稿する必要があるかもしれません。

+0

変数$ outboundの例を追加しました。 printfで使用される他の変数は似ています。ループには他に何もありません – user947668

+0

完全なソースコードが追加されました。 – user947668

関連する問題