I want to get only the version of php installed on CentOS.

Output of php -v

PHP 7.1.16 (cli) (built: Mar 28 2018 13:19:29) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2018 Zend Technologies

I tried this following:

php -v | grep PHP | awk '{print $2}'

But the output I got was:

7.1.16
(c)

How can I get only 7.1.16?

  • 7
    ... | head -1 or there might be better ways – Vlastimil Sep 26 at 8:50
  • Oh, head -1 is very simple and elegent. Thanks man. – The One Sep 26 at 9:19
up vote 12 down vote accepted

On my system:

$> php -v | grep ^PHP | cut -d' ' -f2
7.0.32-0ubuntu0.16.04.1

as grep PHP matches every PHP string it encounters.

The ^PHP means "match only the string 'PHP' when it is at the start of a line".

Obviously, this works if the output format of php -v is consistent across versions/builds.

For reference, the whole output was:

PHP 7.0.32-0ubuntu0.16.04.1 (cli) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
    with Zend OPcache v7.0.32-0ubuntu0.16.04.1, Copyright (c) 1999-2017, by Zend Technologies
  • This answer was great in a sense that i can utilize it to grep the version of httpd version too :P httpd -v | awk '/^Server version/{print $3}' | cut -d'/' -f2 – The One Sep 27 at 1:13

Extending Jeff Schaller's answer, skip the pipeline altogether and just ask for the internal constant representation:

$ php -r 'echo PHP_VERSION;'
7.1.15

You can extend this pattern to get more, or less, information:

$ php -r 'echo PHP_MAJOR_VERSION;'
7

See the PHP list of pre-defined constants for all available.

The major benefit: it doesn't rely on a defined output format of php -v. Given it's about the same performance as a pipeline solution, then it seems a more robust choice.


For reference, here are timings for various test cases, ordered fastest first:

$ time for (( i=0; i<1000; i++ )); do php -v | awk '/^PHP [0-9]/ { print $2; }' >/dev/null; done

real    0m13.368s
user    0m8.064s
sys     0m4.036s

$ time for (( i=0; i<1000; i++ )); do php -r 'echo PHP_VERSION;' >/dev/null; done

real    0m13.624s
user    0m8.408s
sys     0m3.836s

$ time for (( i=0; i<1000; i++ )); do php -v | head -1 | cut -f2 -d' ' >/dev/null; done

real    0m13.942s
user    0m8.180s
sys     0m4.160s
  • 25
    This is really the only correct answer. There is no guarantee that different builds of PHP will have the same output format for php -v – fluffy Sep 27 at 6:24
  • This was actually the first solution that came to my head. While trying to parse the output is worlds faster, it probably isn't as reliable as compiling the code and running it. – Ismael Miguel Sep 29 at 2:05
  • @IsmaelMiguel I had presumed the opposite: compile and execute would be faster than fork a pipeline. However I found from timing experiments that there's no statistical difference in run-time for either solution. – bishop Oct 1 at 13:54
  • 1
    Well, you have the overhead of doing PHP > opcode, opcode > C and C to machine language. This overhead is always constant. PHP may have opcache enabled, which shortens this time by a lot. On the other hand, you have to spawn processes and pass output to input and what-not. I would expect php to be slower when ran a few times (5-10), compared to parsing the output. but thank you for the tests. – Ismael Miguel Oct 1 at 14:33

If you've installed php via the package manager (e.g. RPM or yum), then you can query the version from there:

rpm -q --queryformat="%{VERSION}" php

Alternatively, you can ask php to tell you its version directly:

php -r 'echo phpversion();'

There are different ways, I like to use look behind:

php -v | grep -Po '(?<=^PHP )[^ ]+'

or

php -v | grep -Po '(?<=PHP )([0-9.]+)'
  • minor tip: the \ is unnecessary in the second regex; .'s normal meaning would be useless inside a character class, so it's already treated as literal by default – dn3s Sep 27 at 0:44
  • wow, that was a pain. is there any way to put a single backslash in ` tags? doubling up the slash didn't work – dn3s Sep 27 at 0:45
  • @dn3s quote the pattern, it works for me with single backslash ... – Ravexina Sep 27 at 6:59
  • oh i meant, i just wanted a single \ character enclosed in code tags – dn3s Sep 27 at 23:18
  • Posting a comment while giving a down vote would be appropriate... – Ravexina Sep 29 at 22:12

Since you started with awk, here's an awk solution:

$ php -v | awk '/^PHP/{print $2}'
7.2.10
php -v | awk NR==1'{print $2}'

Or

php -v | awk '{print $2; exit}'
  • 1
    You can also print just the first line by saying awk '{print $2; exit}' – fedorqui Sep 27 at 9:16

If you want to do it with just a single function being piped, you can try using sed like this:

php -v | sed -e '/^PHP/!d' -e 's/.* \([0-9]\+\.[0-9]\+\.[0-9]\+\).*$/\1/'

First it deletes any line that doesn't begin with PHP, then it clips the version from that line assuming it is the first sequence in the form of x.y.z.

Or, if you want something closer to your original script, simply put ^ in the front of your grep pattern to only look for lines that start with PHP:

php -v | grep ^PHP | awk '{print $2}'
  • I like the way it worked by just adding ^ in front of grep pattern. Brilliant. – The One Sep 27 at 1:12

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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