3

I have this file:

header:
  title: hello
  version: 1.2.3

I want to extract the version number.

My original attempt was

grep ^\s+version:\s+(\d\.\d\.\d) file.txt

but that produced empty output. After suggestions in the comments, I tried

grep -P '^\s+version:\s+(\d\.\d\.\d)' file.txt

but I get " version: 1.2.3" instead of "1.2.3".

What am I doing wrong?

7
  • grep uses a very basic regex by default, your regex works with grep -P (at least when quoted...).
    – pLumo
    Apr 9, 2020 at 8:26
  • 1
    Also, don't forget to quote your regex.
    – AdminBee
    Apr 9, 2020 at 8:26
  • 1
    That is normal behavior, you want \K or (?<=...)
    – pLumo
    Apr 9, 2020 at 8:30
  • 4
    Standard sed: sed -n 's/.*version: //p' file
    – Kusalananda
    Apr 9, 2020 at 8:39
  • 1
    In awk: awk '/version/ { print $2 }' yourfile.txt
    – stackzebra
    Apr 9, 2020 at 17:54

2 Answers 2

11

grep uses Posix Basic Regex (BRE) by default which does not support your notation.

Use grep -E to use Posix Extended Regex (ERE) and grep -P to use Perl Compatible Regex (PCRE) if available.

Your notation works with grep -P:

grep -P '^\s+version:\s+(\d\.\d\.\d)' file.txt

This works with BRE:

grep '^ \+version: \+\([0-9]\.[0-9]\.[0-9]\)' file.txt

Output:

  version: 1.2.3

Note, that the capture group is not necessary here, as grep doesn't do anything with it.


If you want the version nr only., use \K and -o option:

grep -Po '^\s+version:\s+\K\d\.\d\.\d' file.txt

Output:

1.2.3

With BRE, this is not possible, you will need to chain two grep commands:

grep 'version: ' file.txt | grep -o '[0-9]\.[0-9]\.[0-9]'

or use sed (credits @Kusalananda):

sed -n 's/.*version: //p' file.txt
2
  • Is there any reason to use a capture group in your first two commands? The group isn't actually used anywhere as far as I can see.
    – terdon
    Apr 9, 2020 at 8:42
  • That is just taken from the Q, I added a note that it's not necessary
    – pLumo
    Apr 9, 2020 at 8:43
3

According the comment of pLumo and How to use grep to get anything just after name a working command could be

 grep -oP "(?<=version: )(\d\.\d\.\d)" file.txt
1
  • 2
    Problem with lookbehind is that it has to be fixed number of characters, which does not work when with \s+ or \s*. I usually prefer keep-out notation \K if possible.
    – pLumo
    Apr 9, 2020 at 8:36

You must log in to answer this question.

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