0

I need to parse a part of the string in bash:

#string1=$(grep "build_no" /etc/build_file)
#val=$(echo $string1 | cut -d'=' -f 2)
#echo $val
"7.6.0-custom-build"

From the above string, I want to be able to extract "7.6.0". So I did:

#current_build=$(echo $val | cut -d'-' -f 1)

But the closing quote is missing at the end:

#echo $current_build
"7.6.0

How can I fix this?

Also, if I have another variable:

#echo $other_build
"7.1.0"

Can I compare the two with the intent of finding the higher of the two builds as follows?

#if [ "$current_build" \< "$other_build" ]; then
...
#else
...
#fi

Thanks!

Maddy
  • 1,319
  • 3
  • 22
  • 37
  • Does the double-quotes come as part of the string or just for storing in variable? – Inian Mar 03 '17 at 08:52
  • Possible duplicate of [How compare two strings in dot separated version format in Bash?](http://stackoverflow.com/questions/4023830/how-compare-two-strings-in-dot-separated-version-format-in-bash) – Inian Mar 03 '17 at 08:55
  • @Inian: The quotes come as part of the string. – Maddy Mar 03 '17 at 09:02
  • @Inian: The link you provided has solution to the comparison question, but it does not fully address the issue. Suppose I have `7.1.0 #15` and `7.1.0 #14`. The version of the image (`#15` and `#14`) would be ignored and they'd be deemed equal. – Maddy Mar 05 '17 at 04:02
  • @Maddy none of the answers provided worked for you? – George Vasiliou Mar 06 '17 at 08:26

3 Answers3

0

You can try this -

 var1="7.6.0"
 var2="7.1.0"
 awk -v var1="$var1" -v var2="$var2" 'BEGIN{ if(var1 > var2) {print "higher"} else {print "lower"}}'
higher
VIPIN KUMAR
  • 3,019
  • 1
  • 23
  • 34
0

If your input string might contain various nonnumeric artefacts which should be stripped off from the beginning and the end, you can use something like this.

clean_numeric () {
    local trim
    local value
    trim=${1%%[0-9]*}
    value=${1#$trim}
    trim=${value##*[0-9]}
    value=${value%$trim}
    case $value in
      *[!-0-9.]* )
        echo "clean_numeric: invalid input $1" >&2
        return 1 ;;
    esac
    echo "$value"
}

This is a generic function which you could call on something like

string1=$(grep "build_no" /etc/build_file)
#val=$(echo $string1 | cut -d'=' -f 2)
val=${string1#*=}
final=$(clean_numeric "${val%%-*}")

Notice the preference for using the shell's built-in string substitution features, which is both more succinct and more efficient (and more readable, once you familiarize yourself with the syntax) than using external processes for trivial substitution.

You seem to be asking about adding a quote if one is missing, but normalizing numbers to just numbers (and then adding quotes back around the number if you really need to) would seem like a simpler and more manageable approach.

tripleee
  • 175,061
  • 34
  • 275
  • 318
0

You can use perl in sed-like replacement syntax and achieve whatever you need using Perl Regexp Grouping:

$ echo "$a"
"7.6.0-custom-build"

$ perl -pe 's/(^.)(.*?)-(.*?)(.$)/\1\2\4/' <<<"$a"
"7.6.0" 
#Input string is divided in groups :
#1st group contains the first character " or ' or whatever it is. 
#2nd group match any char for zero or more times in use with the "non-greedy operator `?`"
#4th group match the end of line with the previous char (either " or ' or whatever
#The whole input string is replaced by group 1-2-4

$ perl -pe 's/(^.)(.*?)-(.*?)(.$)/\2/' <<<"$a"
7.6.0
# Similarly , without the 1st and last chars = only group2

$ perl -pe 's/(^.)(.*?)-(.*?)(.$)/\2/;s/[.-]//g' <<<"$a"
760
#Like before but with an extra substitution to remove literal dots or dashes that use to exist in version.

With the last command you can convert any string representing a version number to a flat number :
7.6.0 to 760
7.1.0 to 710

Thus you can directly compare them as integers with bash -gt / -lt operators.

Including dash in the last example you can also transform versions like :
7.6.1-1 to 7611.

PS: I prefer perl -pe over sed because:
(a) perl supports non-greedy regexp while sed does not support them

(b) serial substitutions of perl refer to the previously transformed text , while on sed each substitution refers to the initial - incoming text/stream

(c) Perl will work on the same way in all the systems that they do have perl installed (i.e Debian, BSD, MAC, wherever) and that makes it fully portable.

George Vasiliou
  • 6,130
  • 2
  • 20
  • 27