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)
malat
  • 3,032
yael
  • 13,106
  • 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. https://unix.stackexchange.com/a/382537/5132 https://unix.stackexchange.com/a/125241/5132 – JdeBP Mar 10 '20 at 14:22

4 Answers4

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.

Chris Davies
  • 116,213
  • 16
  • 160
  • 287
  • 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. – Gordon Davisson Mar 09 '20 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. – Chris Davies Mar 09 '20 at 22:40
  • 1
    Linux. As easy as possible, as complex as needed. – WGRM Mar 09 '20 at 22:59
  • Is the space at the end of the pattern intentional? – Kusalananda Mar 09 '20 at 23:00
  • 4
    @Kusalananda yes it is. Anchors the pattern to avoid 7.59 or even 7.5.9. – Chris Davies Mar 09 '20 at 23:14
  • Apart from the better readability (in my opinion), another advantage of using grep here is that you could immediately "silence" any potential "No such file or directory" warning (e.g. if this script would be run on debian) directly with the -s flag. – Asmus Mar 11 '20 at 07:26
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.)

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
  • @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)}' – Stéphane Chazelas Mar 10 '20 at 07:02
  • I've realized it immediately after posting it, sorry. I should install a userscript that give me some grace period before embarassing myself. –  Mar 10 '20 at 07: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
kojiro
  • 4,644