command in bash contains printf but the format is not hand over to variable

28 views Asked by At

Bashversion: 4.2.46 OS: linux 3.10.0-1160.108.1.e17

the following command with with printf shall provide three columns with 10 Characters. Running this only in bash all works fine.

$ free -h | grep Mem | awk '{printf "%-10s %-10s %-10slala\n",$2,$3,$4}'
7.6G       2.0G       3.4G       lala

Using a variable to do so, the format will be lost.

$ LINE=$(free -h | grep Mem | awk '{printf "%-10s %-10s %-10s\n",$2,$3,$4}')
$ echo $LINE
7.6G 2.0G 3.4G

Where go I wrong?

I'm apreciate to get advise from experts

Thank youe

F.

I've tried this so far:

$ LINE=$(free -h | grep Mem | awk '{printf "%-10s %-10s %-10s\n",$2,$3,$4}')
$ LINE=`free -h | grep Mem | awk '{printf "%-10s %-10s %-10s\n",$2,$3,$4}'`
$ LINE=${free -h | grep Mem | awk '{printf "%-10s %-10s %-10s\n",$2,$3,$4}'}
1

There are 1 answers

2
Paul Hodges On

You need quotes around "$LINE". Always mind your quotes. awk is doing it right, but then you are throwing away the spaces.

$ LINE=$(free -h | grep Mem | awk '{printf "%-10s %-10s %-10s\n",$2,$3,$4}')
$ echo $LINE
7.6G 2.0G 3.4G
$ echo "$LINE"
7.6G       2.0G       3.4G

(I edited in your memory values from above.)

What are you doing with $LINE? If you are literally just doing that printf then why bother with all the trouble? Just use the command as you showed it... except, don't. Try to never use multiple regex engines in a single command. Why waste the system resources on a grep just to pass the result to awk when awk can already handle that?

$ free -h | awk '/^Mem:/{printf "%-10s%-10s%-10slala\n", $2, $3, $4}'
15G       1.4G      214M      lala

Passing the result back to a variable (which you shouldn't generally capitalize, btw) just to pretty-print it out isn't needed unless you are changing the formatting.

If you need those values for other things later, save them and format-print them separately.

$ read -r _ totmem usemem fremem _ < <( free -h | grep ^Mem: )
$ printf "total: %-10s used: %-10s free: %s\n" "$totmem" "$usemem" "$fremem"
total: 15G        used: 1.4G       free: 203M

or

$ read -ra freemem < <( free -m | awk '/^Mem:/{print $2, $3, $4}' )
$ (( ${#freemem[2]}<4 )) && printf "total : %10s\nused  : %10s\nfree  : %10s\n" "${freemem[@]}"
total :      15885
used  :       1434
free  :        225

or even

$ freemem=( $(free -h) ); printf "%-10s" "${freemem[@]:7:3}"; echo lala
15G       1.4G      217M      lala

which probably uses built-in versions of both printf and echo, so only spawns one subshell for free.

I didn't downvote because it can be hard to figure out how to phrase your search on things like this, but I highly recommend reading the documentation and keeping in mind that whitespaces are metacharacters that must be handled accordingly.