Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sed: Extract version number from string

Tags:

sed

Input: adcheck (CentrifyDC 4.4.3-421)

Desired output: 4.4.3

What I thought would work:

/usr/share/centrifydc/bin/adcheck --version | sed -n '/Centrify DC /,/-/p'

But that outputs nothing??

Thank you!

like image 248
Drew M. Avatar asked Jul 11 '11 19:07

Drew M.


4 Answers

sed 's/[[:alpha:]|(|[:space:]]//g' | awk -F- '{print $1}' <<< "(CentrifyDC 4.4.3-421)"

output: 4.4.3

Using [:space:] to remove extras spaces.

sed is used to remove unwanted characters and awk -F- means use - as field separator

like image 136
Eric Fortis Avatar answered Oct 20 '22 23:10

Eric Fortis


Your solution does not work because you are trying to use addresses to select a piece of a line, but addresses just select a bunch of lines. Your code /Centrify DC /,/-/p would print all lines between one line which contains Centrify DC and another line which contains -. It does not work inside one line only, however

What you want is to remove everything from the line, except the version number. I would recommend you to group the version number and replace all the content of the line by it:

$ echo "adcheck (CentrifyDC 4.4.3-421)" | sed 's/^.*[^0-9]\([0-9]*\.[0-9]*\.[0-9]*\).*$/\1/'
4.4.3

Here we put the version number in a group with \([0-9]*\.[0-9]*\.[0-9]*\) and replace all the line by the group (referenced by \1).

If your input has more than one line, it may need some tunneling:

$ cat file
adcheck (CentrifyDC 4.4.3-421)
another line
still another line
$ sed 's/^.*[^0-9]\([0-9]*\.[0-9]*\.[0-9]*\).*$/\1/' file
4.4.3
another line
still another line

In this case, pass the -n flag to sed for inhibiting the default printing. Then, give an address to the s/// command (such as /adcheck (CentrifyDC /) for guaranteeing that the replacement will occur only in the line which matchs the address. Finally add the p flag to the s/// command - it will print the line just after the replacement:

$  sed -n '/adcheck (CentrifyDC /s/^.*[^0-9]\([0-9]*\.[0-9]*\.[0-9]*\).*$/\1/p' file
4.4.3
like image 35
brandizzi Avatar answered Oct 20 '22 23:10

brandizzi


Corrected version of "What you thought would work":

/usr/share/centrifydc/bin/adcheck --version | sed 's|.*CentrifyDC \([0-9\.]*\).*|\1|'

Output:

4.4.3
like image 5
ssapkota Avatar answered Oct 20 '22 23:10

ssapkota


one-line perl script

perl -pe '($_)=/([0-9]+([.][0-9]+)+)/' YOURFILE.TXT

or a bit more longer but handles multiple versions:

perl -nle 'print $v if ($v)=/([0-9]+([.][0-9]+)+)/' YOURFILE.TXT

examples using the first command line

$> V=$(perl -pe '($_)=/([0-9]+([.][0-9]+)+)/'<<<'adcheck (CentrifyDC 4.4.3-421)')
$> echo "$V"
4.4.3

$> V=$(perl -pe '($_)=/([0-9]+([.][0-9]+)+)/' <<< 'dos2unix-8.2.3-beta.zip')
$> echo "$V"
8.2.3

$> echo 'A2 33. Z-0.1.2.3.4..5' | perl -pe '($_)=/([0-9]+([.][0-9]+)+)/'
0.1.2.3.4

$> gcc --version | perl -pe '($_)=/([0-9]+([.][0-9]+)+)/'
4.7.3

$> bash --version | perl -pe '($_)=/([0-9]+([.][0-9]+)+)/'
4.2.45

$> meld --version | perl -pe '($_)=/([0-9]+([.][0-9]+)+)/'
1.6.1

$> uname -a | perl -pe '($_)=/([0-9]+([.][0-9]+)+)/'
3.8.0

$> perl -pe '($_)=/([0-9]+([.][0-9]+)+)/' /etc/issue
13.04

Note: the first command line extracts the version without the final carriage return (I mean the \n). If this is an issue, use the second version or wrap the first command line within echo:

$> echo $( perl --version | perl -pe '($_)=/([0-9]+([.][0-9]+)+)/' )
5.14.2

Unfortunately, if there are multiple lines containing version numbers, these version numbers will be concatenated:

$> echo $(gwenview --version | perl -pe '($_)=/([0-9]+([.][0-9]+)+)/' )

4.8.44.10.54.10.4

In order to extract one version per line, the one-line script has to be changed:

perl -pe 'if(($_)=/([0-9]+([.][0-9]+)+)/){$_.="\n"}'

example:

$> gwenview --version | perl -pe 'if(($_)=/([0-9]+([.][0-9]+)+)/){$_.="\n"}' 
4.8.4
4.10.5
4.10.4

To extract solely the first version number and appending carriage return (I mean new line \n), I advice:

perl -pe 'if(($v)=/([0-9]+([.][0-9]+)+)/){print"$v\n";exit}$_=""'

example:

$> gwenview --version | perl -pe 'if(($v)=/([0-9]+([.][0-9]+)+)/){print"$v\n";exit}$_=""'
4.8.4

For information, my sed attempt is not as good. Who knows how to obtain the same behavior as my perl scripts but using sed?

sed 's/\([0-9][0-9]*[.][0-9][0-9.]*\)/\n\1/'

If you think you can improve these scripts, please feel free to post a comment :)

like image 4
oHo Avatar answered Oct 21 '22 01:10

oHo