Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to concatenate strings formatted with printf in bash

Tags:

bash

shell

printf

I need to concatenate several strings in loop and assign result to variable:

Formatted string example:

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

From my view it should work like this:

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

But it doesn't :(

UPD:

Full code listing below:

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
like image 612
user947668 Avatar asked Apr 13 '13 21:04

user947668


People also ask

How do I concatenate strings in Bash?

The += Operator in Bash Bash is a widely used shell in Linux, and it supports the '+=' operator to concatenate two variables. As the example above shows, in Bash, we can easily use the += operator to concatenate string variables.

Can you concatenate C style strings?

You can concatenate two C-style strings in C++ using strcat() function.

How do you concatenate in a script?

String concatenation is the process of appending a string to the end of another string. This can be done with shell scripting using two methods: using the += operator, or simply writing strings one after the other.


1 Answers

Use double quotes around $result and all other variables that may contain blanks and other special characters if they are to be used as a single argument to a program or built-in function:

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

If you just want to assign the result of printf to a variable (as you did), you can also use

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

BTW: there also a += assignment operator that just appends to strings (see bash man page, section PARAMETERS).

In the full code listing, a pipe sign is missing after the 'done' before the second 'while read i'.

And when you call

echo $result

the contents of $result is already lost, since the printf is called in a sub process created by the pipe sign after 'do du ...'. The parent processes haven't access to the (environment) variables of the sub process.

I'd rather rewrite the code to something like

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"

The read < <(cmd) expression is similar to cmd | read but the former puts the command in the sub process instead, while the read is executed in the main process. This way, the variables set by read can be used in subsequent commands, too.

like image 86
Jacob Avatar answered Sep 27 '22 18:09

Jacob