226

I want to parse a variable (in my case it's development kit version) to make it dot(.) free. If version='2.3.3', desired output is 233.

I tried as below, but it requires . to be replaced with another character giving me 2_3_3. It would have been fine if tr . '' would have worked.

  1 VERSION='2.3.3' 
  2 echo "2.3.3" | tr . _
prayagupa
  • 4,897
  • 13
    No, it doesn't require: echo "2.3.3" | tr -d .. – manatwork Dec 12 '13 at 14:59
  • 1
    @manatwork Great, that works. You can post it as answer. Thanks – prayagupa Dec 12 '13 at 15:04
  • 2
    Lot of good answers. But if I can second-guess the objective, be warned about 2.11.3 and 2.1.13... ;-) Consider adding padding zeroes to numbers. – Rmano Dec 12 '13 at 16:06
  • 1
    @Rmano You mean something like VERSION='2.30.3100'? No matter what just .'s are removed with all of the answers here. – prayagupa Dec 12 '13 at 16:13
  • 2
    @PrayagUpd --- I simply meant that if you will use the number after the conversion for comparisons (as to say if "is this version newer or the same") you should take care of cases like 2.11.3 and 2.1.13 --- they seems the same after dot removal, but clearly 2.11.3 is newer. Also, 2.11.3 is newer than 2.1.14, but comparing 2113 and 2114 will lead to the wrong answer. I remember a bug somewhere for this... – Rmano Dec 12 '13 at 16:19
  • @Rmano Got you. But my purpose is to identify the version in my project and get the development kit of that version located somewhere in filesystem. You can go through my bash file. Thx anyway for for warn :) – prayagupa Dec 12 '13 at 16:27
  • @PrayagUpd so how do you differentiate the directories for version 2.11.3 and 2.1.13? Or are you sure you have one-digit subversion ever? – Rmano Dec 12 '13 at 16:38
  • @Rmano Looking over kit's history, it has 1-digit sub- version so far. – prayagupa Dec 12 '13 at 16:43

6 Answers6

252

There is no need to execute an external program. bash's string manipulation can handle it (also available in ksh93 (where it comes from), zsh and recent versions of mksh, yash and busybox sh (at least)):

$ VERSION='2.3.3'
$ echo "${VERSION//.}"
233

(In those shells' manuals you can generally find this in the parameter expansion section.)

manatwork
  • 31,277
  • 59
    For further detail, the syntax of the above answer is ${string//substring/replacement}, where apparently the lack of the final forward slash and replacement string are interpreted as delete. See here. – sherrellbc Jan 06 '16 at 18:19
  • 7
    Right, man bash says it clearly in the Shell Parameter Expansion section: “${parameter/pattern/string} (…) If string is null, matches of pattern are deleted and the / following pattern may be omitted.” – manatwork Jan 06 '16 at 18:49
  • 1
    My issue was that the version number came like this "1.0.0" and I wanted just the number so follow what @manatwork suggested I changed in: "${VERSIONNUM//'"'}" however I insert even ' 'because otherwise it wouldn't recognise the "" like string to take off. – Alexiscanny Sep 14 '16 at 12:53
  • 1
    @Alexiscanny, you mean literal " are present in the value? I'm afraid this counts as new question, but try to just escape the doublequote: "${VERSIONNUM//\"}" http://pastebin.com/3ECDtkwH – manatwork Sep 14 '16 at 13:03
  • 1
    Superb!! works on -ash too! – Fr0zenFyr Jan 04 '17 at 11:33
  • @Fr0zenFyr, that would be busybox' ash (when built with ASH_BASH_COMPAT )even though that's a ksh feature, not bash)) . The original ash didn't have it and I'm not aware of any other ash derivative (only tried dash and FreeBSD sh though) that has it. – Stéphane Chazelas Mar 10 '17 at 12:00
  • Not wanting to be a OT or a killjoy, but following the intention of the above, it would be far better to ensure that the digits are separated. For instance, compare nominal versions with 2.11.1 and 2.1.12 . The above method will fail dramatically. In fact so would 3.0 vs 2.1.6 – Konchog Aug 14 '19 at 06:22
  • So, again if wanting to get versions - especially for comparison, it would be far better to use "sort -V" – Konchog Aug 14 '19 at 06:32
137

By chronological order:

tr/sed

echo "$VERSION" | tr -d .
echo "$VERSION" | sed 's/\.//g'

csh/tcsh

echo $VERSION:as/.//

POSIX shells:

set -f
IFS=.
set -- $VERSION
IFS=
echo "$*"

ksh93/zsh/mksh/bash/yash (and busybox ash when built with ASH_BASH_COMPAT)

echo "${VERSION//.}"

zsh

echo $VERSION:gs/./
  • 1
    tr -d deleted even single char from the set. For Ex i want to delete DCC_ from "DCC_VersionD", It deletes DCC and D. Expected output : VersionD. Actual Output : Version. sed worked like a charm. :) thanks for the post. – kayle May 21 '18 at 11:30
32

In addition to the successful answers already exists. Same thing can be achieved with tr, with the --delete option.

echo "2.3.3" | tr --delete .
echo "2.3.3" | tr -d .       # for MacOS

Which will output: 233

dialex
  • 103
daz
  • 430
10

You should try with sed instead

sed 's/\.//g'
Pablo A
  • 2,712
fduff
  • 5,035
7
echo "$VERSION" | tr -cd [:digit:]

That would return only digits, no matter what other characters are present

  • Only if there's no file called :, d, i, g or t in the current directory and you're using a shell that doesn't complain upon non-matching globs and leaves them asis (most Bourne-like ones and rc-like ones) or a shell that doesn't support [...] globs (like fish). – Stéphane Chazelas May 29 '20 at 15:17
5

Perl

$ VERSION='2.3.3'                                     
$ perl -pe 's/\.//g' <<< "$VERSION"           
233

Python

$ VERSION='2.3.3'                                     
$ python -c 'import sys;print sys.argv[1].replace(".","")' "$VERSION"
233

If $VERSION only contains digits and dots, we can do something even shorter:

$ python -c 'print "'$VERSION'".replace(".","")'
233

(beware it's a code injection vulnerability though if $VERSION may contain any character).

AWK

$ VERSION='2.3.3'
$ awk 'BEGIN{gsub(/\./,"",ARGV[1]);print ARGV[1]}' "$VERSION"
233

Or this:

$ awk '{gsub(/\./,"")}1' <<< "$VERSION"
233