1

I'm trying to find a nice way of checking some text in order to set a variable. For instance to perform the logic: 'if the version string is 1.x then set a flag'. One way of doing this is:

versionFlag="0"
if grep -q "^1.*" versionfile; then
  versionFlag="1"
fi

which is a little verbose. If I want to switch on multiple possibilities then that's easier:

case `grep "^1.*" versionfile` in
  1.*)
    echo "version 1"
    ;;
...
esac

But is there a nice one line way of just setting a flag to be true or false if some text matches a regexp or a wildcard?

4 Answers4

5
versionFlag=`grep "^1.*" /tmp/test | wc -l`

versionFlag is then set to 0. Any data in test matches, versionFlag is set to the number of lines that match, so

if [ $versionFlag == 0 ] ; then
  echo false
else
  echo true 
fi

edit: this can be done even more simply

versionFlag=$(grep "^1.*" /tmp/test -c)

which will return a count of instances in the file

Andy
  • 5,280
2

You can do something like this in bash 3.x (older versions don't support regex matching)

version=`cat versionfile`
[[ $version =~ "^1.*" ]] && versionFlag=1
James
  • 7,809
0

There isn't a ternary operator (e.g. ?:) in bash, so you are stuck with your if, then construct over multiple lines. You could use a different language that does have a ternary operator (PERL for example).

Mind you, a lot of folk discourage use of ternary operators as they aren't as easy to read in code - in other words, your comments end up longer than the multiple lines of code would have been.

I doubt there is a performance benefit of either method.

dunxd
  • 9,874
0

Actually, this construct:

[[ $version =~ ^1\.+ ]] && versionFlag=1

is easily extended to support the "no-match" case; just do this:

[[ $version =~ ^1\.+ ]] && versionFlag=1 || versionFlag=0

Incidentally, note the change from '*' to '+' in the regex. Using the star, the regex will still incorrectly match on a version value of "10". (The '*' modifier means "match zero or more occurrences", i.e., you still don't need to have a decimal point; the '+' modifier means "match one or more occurrences".) Making this change will, however, mean that "1" (i.e., a value without a decimal) will not match; this might or might not be a problem for your application.

There is also a way to do this without using the regex-match operator, if you don't have it; try this:

[[ ${version#1.} != ${version} ]] && versionFlag=1 || versionFlag=0

This is just a pattern-match, not a regex, so if you really need regex functionality, it won't work, but for simple stuff, it's great. (If you're not familiar with this form of parameter expansion, the "${version#1.}" construct expands to the value of "version", but with the post-'#' pattern removed from the beginning of the value if it was originally there. Example: If "version" has a value of "1.03", the result of "${version#1.}" is "03". Since this differs from the original value, the "!=" test succeeds.)