Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. 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

On OS X, system_profiler SPHardwareDataType outputs:

Hardware Overview:

  Model Name: MacBook Pro
  Total Number of Cores: 4
  L2 Cache (per Core): 256 KB
  L3 Cache: 8 MB
  Memory: 8 GB

I want to get the Memory value, trimmed of whitespaces.

This is what I had:

system_profiler SPHardwareDataType | grep --color=never -E '^ +Memory: ' | cut -d ':' -f 2

Not ok. It keeps the whitespace.

I switched to this:

system_profiler SPHardwareDataType | perl -ne 'if(/^ +Memory: (.*)$/){print $1;}'

and I'd like to ask:

  • Could this be made more concise in Perl?

The braces annoy me, often I type them wrong. Having to put the condition in () is also bothersome. The semicolon is bothersome.

  • Could this be made as concisely using more basic UNIX tools? (grep/sed/awk)?

I think this idiom "grep for pattern and replace" must be very common to extract info. I am a beginner but an experienced sysadmin/devops perhaps could recommend the best line to use?

Note: I do not use this line I like..

system_profiler SPHardwareDataType | sed -Ene 's/^ +Memory: (.*)$/\1/g p'

because extended regexes (-E are -r on some platforms? possible?) and fundamentally because, although I understand that sed works on lines, -n suppresses output unless I explicitly p print it, s//g is a normal regex substitute.. and that commands following a match are only executed on matching lines.. I am puzzled by the fact that s//g in reality is an action in itself.. so I would expect p to require a ; before it.. odd that you can both replace and use the match as a condition to execute the comand.. is that line correct at all?

share|improve this question
up vote 1 down vote accepted

Awk would make it most consise:

system_profiler SPHardwareDataType | awk  -F': ' '/Memory:/{print $2}'
share|improve this answer
Does not capture the unit of measure, in that case GB, which was desirable.. perhaps a capture "from field 2 to NF"? How would you write that? – Robottinosino Mar 29 '13 at 19:38
Not sure, so I simply edited the answer to use a proper -F parameter :) – Dennis Kaarsemaker Mar 29 '13 at 19:46
This is the best I have found anywhere. The -F to include both the colon and the space trims the rest of the line already, in one go. Very compact, exactly right.. LIKE! – Robottinosino Mar 29 '13 at 20:11

This is all you really need for the Perl one:

system_profiler SPHardwareDataType | perl -nle '/ry:\s*(.*)/ && print $1'

Some other choices:

  • system_profiler SPHardwareDataType | /bin/grep Me | gawk '{print $2,$3}'

    Using /bin/grep eliminates the need for --color=never. grep is defined as an alias to grep --color=auto in /etc/bash.bashrc (at least it is on most Linux distros and, I guess, on OSX).

  • system_profiler SPHardwareDataType | /bin/grep Me | /bin/egrep -o '[1-9]+.+'

    The -o causes grep toprint only the matched characters.

  • system_profiler SPHardwareDataType | tail -n 1 | cut -d ' ' -f 4,5

  • system_profiler SPHardwareDataType | tail -n 1 | sed 's/.*: //g'

share|improve this answer
system_profiler SPHardwareDataType | sed -n 's/^ *Memory: //p'

p here is a flag to the s command (like g), not the p command, and means print the pattern space if the substitution takes place. You don't need g here, since the pattern can only match once.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.