2

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

10

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
  • 1
    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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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