5

In bash I did the following. This if expression will evaluate to true if the Redhat version is 7.5 or 7.6.

if [[ ` cat /etc/redhat-release  | awk '{print $7}' ` == "7.5" ]] || [[ ` cat /etc/redhat-release  | awk '{print $7}' ` == "7.6" ]]
then
.
.
.

Can we do it in a more elegant way with regular expressions?

This is the content of /etc/redhat-release:

cat /etc/redhat-release
Red Hat Enterprise Linux Server release 7.6 (Maipo)
1
  • Of course, using the VERSION_ID from the intended-to-be-machine-readable /etc/os-release is easier than parsing the human-readable string in /etc/redhat-release. Luckily for doing that, this is RHEL (where bug #1240624 was fixed in version 7.2) and not CentOS or Debian or Arch. unix.stackexchange.com/a/382537/5132 unix.stackexchange.com/a/125241/5132
    – JdeBP
    Mar 10, 2020 at 14:22

4 Answers 4

15

Far simpler just to check the release string directly

if grep -q 'release 7\.[56] ' /etc/redhat-release
then ...

The grep command matches by regular expression. The [56] atom matches 5 or 6, allowing the pattern to match on 7.5 or 7.6. Since . matches any character I've escaped it with a backslash so that it matches a literal dot. The trailing space ensures there are no other characters following the matched version string.

6
  • 1
    Personally, I'd use grep -q 'release 7[.][56] ' -- IMO still fairly readable, and you don't have to worry about it failing when release 705 comes out. (or... does Red Hat use alpha-beta numbers like 7a5?) The big advantage of [] instead of escaping is that you don't have to worry about whether you might have to double-escape (or triple, or...) based on what kind of quotes it's in, etc. Mar 9, 2020 at 22:38
  • That's an interesting approach. I had to read it twice though, so maybe I should have just gone for \. in the first place. Mar 9, 2020 at 22:40
  • 1
    Linux. As easy as possible, as complex as needed.
    – WGRM
    Mar 9, 2020 at 22:59
  • Is the space at the end of the pattern intentional?
    – Kusalananda
    Mar 9, 2020 at 23:00
  • 4
    @Kusalananda yes it is. Anchors the pattern to avoid 7.59 or even 7.5.9. Mar 9, 2020 at 23:14
11

You can do this with bash's built-in string matching. Note that this uses glob (wildcard) patterns, not regular expressions.

if [[ $(cat /etc/redhat-release  | awk '{print $7}') == 7.[56] ]]

Or, of we eliminate the UUoC:

if [[ $(awk '{print $7}' /etc/redhat-release) == 7.[56] ]]

or...

if [[ $(cat /etc/redhat-release) == *" release 7."[56]" "* ]]

or even (thanks to @kojiro)...

if [[ $(< /etc/redhat-release) == *" release 7."[56]" "* ]]

(Note that wildcards at the beginning and end are needed to make it match the entire line. The quoted space after the number is to make sure it doesn't accidentally match "7.50".)

Or if you really want to use regular expressions, use =~ and switch to RE syntax:

if [[ $(< /etc/redhat-release) =~ " release 7."[56]" " ]]

(Note that the part in quotes will be matched literally, so . doesn't need to be escaped or bracketed (as long as you don't enable bash31 compatibility). And RE matches aren't anchored by default, so you don't need anything at the ends like in the last one.)

2
  • very nice , this code is what I need
    – yael
    Mar 9, 2020 at 23:03
  • 1
    Consider $(</etc/redhat-release) instead of $(cat /etc/redhat-release)
    – kojiro
    Mar 10, 2020 at 10:42
3

awk can do all the work of cat and [[...]] here:

if
  </etc/redhat-release awk -v ret=1 '
    $7 ~ /^7\.[56]$/ {ret=0}
    END {exit(ret)}'
then
  ...

Or just with standard sh syntax with simple wildcard pattern matching:

case $(cat /etc/redhat-release) in
  (*'release 7.'[56]' '*) ...;;
  (*) ...;;
esac
2
  • @pizdelect, that would always exit with 1. If you wanted to exit on first match, you'd still need awk -v ret=1 '$7 ~ /.../ {ret=0; exit}; END {exit(ret)}'. Or awk '$7 ~ /.../ {found=1; exit}; END {exit(!found)}' Mar 10, 2020 at 7:02
  • I've realized it immediately after posting it, sorry. I should install a userscript that give me some grace period before embarassing myself.
    – user313992
    Mar 10, 2020 at 7:03
3

Bash can pull out field 7 of a line using read, and these "/etc/*-release" type files tend to be one line anyway. Consider

read _ _ _ _ _ _ ver _ < /etc/redhat-release
if [[ $ver = 7.[56] ]]; then
    # match
fi

You must log in to answer this question.

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