Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

For example,

If you do free -m | sed -n 2p

I want to work with the output from the last, second to last, and third columns. The problem is I want to keep it consistent and use the output from free once.

I want to be able to keep the output consistent without running the free -m | sed -n 2p and extracting what the three columns that I need three times; I want to be able to do it once. How can I do this?

share|improve this question
    
Just to make sure I'm understanding this correct: You want to generate a dataset, and then generate three new independent datasets based on the original dataset, but without regenerating the original dataset each time? I don't think this can be done simply with piping, but it might be possible with subshelling or temporary files. – Darth Android Jul 18 '12 at 15:59
up vote 3 down vote accepted

You might want to give Awk a whirl for this.

[root@james-ws tmp]# free -m | sed -n 2p
Mem:          3948       3724        223          0        364        852
[root@james-ws tmp]# free -m | sed -n 2p | awk '{print $7, $6, $3}'
852 364 3718
share|improve this answer

You can use named pipes and awk to split the output into 3 sources. Then you can read (once) from each source.

mkfifo pipe1 pipe2 pipe3
free -m | sed -n 2p | awk '{ print $3 >> pipe1; print $6 >> pipe2; print $7 >> pipe3 }'

The named pipes pipe1 et al. act as buffers that you can read from as if they were pipelines.

cat pipe1 | this | that | the-other

or preferably without cat:

this < pipe1 | that | the-other

Note that once you read data from a pipe, the data is gone, just as if your input came from a regular pipe.

share|improve this answer

I think the simplest way to do this would be to store the statistics line in a bash array, and then access the elements of the array:

memStats=( $(free -m | sed -n 2p) )
memStatElements=${#memStats[@]}
echo "last column: ${memStats[memStatElements-1]}"
echo "second-to-last column: ${memStats[memStatElements-2]}"
echo "second column: ${memStats[1]}" # Note that arrays are 0-based, so [1] is the second element
share|improve this answer

I opted to instead just store the free result in a variable and echo each result individually.

This is my end result:

STRINGMEM=$(free -m | sed -n 2p | awk '{ print $7,$6,$3 }'); CACHED=$( echo $STRINGMEM | awk '{print $3}'); BUFFERED=$(echo $STRINGMEM | awk '{print $2}'); ACTIVE=$(echo $STRINGMEM | awk '{print $1}'); ACTIVE=$( (( ($BUFFERED + $CACHED) - $ACTIVE)) ); DATE=$(date +%s);
share|improve this answer

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .