0

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}'}
2
  • Also see Bash Pitfalls #14 (echo $foo).
    – pjh
    Commented Mar 25, 2024 at 17:23
  • 2
    Shellcheck identifies the problem with the code (missing quotes). The report that it produces includes links to more information about the problem and how to fix it. It's a good idea to run Shellcheck on all new and modified shell code.
    – pjh
    Commented Mar 25, 2024 at 17:25

1 Answer 1

1

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.

2
  • 1
    I edited this several times, but it still seems...unnecessarily pompous and snarky to me. Apologies, it isn't intended. Hope it helps. Commented Mar 25, 2024 at 16:40
  • I use "$LINE" in a more or less report with further system information. I will do this in a crontab job to get the history of the memory usage for the current day. Unfortunately, I don't know any other way to find the memory consumption of the last 24 hours. Thanks for the help, the tip with the system resources and use only awk command makes totally sense.
    – falcon68
    Commented Mar 26, 2024 at 4:43

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.