3

I have a web application that is deployed to a server. I am trying to create a script that amoing other things reads the current version of the web application from a properties file that is deployed along with the application.

The file looks like this:

//other content
version=[version number]
build=[buildnumber]
//other content

I want to create a variable that looks like this: version-buildnumber

Here is my script for it:

VERSION_FILE=myfile

VERSION_LINE="$(grep "version=" $VERSION_FILE)"
VERSION=${VERSION_LINE#$"version="}
BUILDNUMBER_LINE=$(grep "build=" $VERSION_FILE)
BUILDNUMBER=${BUILDNUMBER_LINE#$"build="}
THEVERSION=${VERSION}-${BUILDNUMBER}

The strange thing is that this works in some cases but not in others. The problem I get is when I am trying to concatenate the strings (i.e. the last line above). In some cases it works perfectly, but in others characters from one string replace the characters from the other instead of being placed afterwards.

It does not work in these cases:

  • When I read from the deployed file
  • If I copy the deployed file to another location and read from there

It does work in these cases:

  • If I write a file from scratch and read from that one.
  • If I create my own file and then copy the content from the deployed file into my created file.

I find this very strange. Is there someone out there recognizing this?

learningbee
  • 333
  • 1
  • 5
  • 11
Ludwig Magnusson
  • 13,964
  • 10
  • 38
  • 53
  • Can you reproduce it?, Did you try debugging with `set -x`? – KurzedMetal May 07 '12 at 12:35
  • If there is one thing bash is not particularly good at its processing text. I think you will find it much easier to delegate this work to Python, perl, or awk. – nsfyn55 May 07 '12 at 12:39
  • 1
    Looks like you have some stray `$` in there -- `VERSION=${VERSION_LINE#version=}` – glenn jackman May 07 '12 at 13:49
  • Debbugging helped. I think I found the error. In the files that work each line ends with line-feed only. In the files that produce the error, each line ends with carriage-return and line-feed. The carriage-return is a part of the line when the script fails. I need to find out how to exclude the carriage-return. – Ludwig Magnusson May 07 '12 at 13:50
  • 3
    @nsfyn55, I strongly disagree. – glenn jackman May 07 '12 at 13:50
  • 1
    @LudwigMagnusson, either convert the CRNL files with `dos2unix`, or filter out the CR with `sed 's/\r$//'` – glenn jackman May 07 '12 at 13:51
  • @glenn so you've noted you disagree, but failed to provide any reason. I'd be interested to see some samples of bash text processing using only bash built-ins – nsfyn55 May 07 '12 at 14:30
  • 1
    @nsfyn55: http://stackoverflow.com/search?q=user%3A26428+pure+%5Bbash%5D – Dennis Williamson May 07 '12 at 14:36
  • @glenn: to be clear I didn't say text processing is impossible, but most things you can do in 5-10 lines of bash. You can do in 1 line of python or awk. – nsfyn55 May 07 '12 at 15:44
  • @nsfyn55, I was disagreeing with your contention "bash is not particularly good at processing text". I concur that other languages designed specifically for that (sed/awk/perl) will be more terse. – glenn jackman May 07 '12 at 15:50
  • @glenn Your assertions lead to my conclusion. In fact, your statement in itself makes reference to "languages specifically designed for that " which by implication asserts bash was not particularly designed for that purpose. From this it is not a huge logical leap to say its not "particulary good" at said task. – nsfyn55 May 07 '12 at 18:35

2 Answers2

1

Given this foo.txt:

//other content
version=[version number]
build=[buildnumber]
//other content

you can extract a version-build string more easily with awk:

awk -F'=' '$1 == "version" { version = $2}; $1 == "build" { build = $2}; END { print version"-"build}' foo.txt

I don't know why your script doesn't work. Can you provide an example of erroneous output?

From this sentence:

In some cases it works perfectly, but in others characters from one string replace the characters from the other instead of being placed afterwards.

I can't understand what's actually going on (I'm not a native English speaker so it's probably my fault).

Cheers, Giacomo

Giacomo
  • 11,087
  • 5
  • 25
  • 25
  • With your code, the behaviour is acctually still the same. Let me explain the error more in detail with this example: version=3.2.1 build=87 excpected output: 3.2.1-87 Actual output -87.1 It is as if the second string (-87) is placed "on top of" the beginning of the first sting, i.e the first 3 letters are replaced by the second string. – Ludwig Magnusson May 07 '12 at 13:39
1

It is likely that your files have carriage returns in them. You can fix that by running dos2unix on the file.

You may also be able to do it on the fly on the strings you're retrieving.

Here are a couple of ways:

Do it with sed instead of grep:

VERSION_LINE="$(sed -n "/version=/{s///;s/\r//g;p}" $VERSION_FILE)"

and you won't need the Bash parameter expansion to strip the "version=".

OR

Do the grep as you have it now and do a second parameter expansion to strip the carriage return.

VERSION=${VERSION_LINE#$"version="}
VERSION=${VERSION//$'\r'}

By the way, I recommend habitually using lowercase or mixed case variable names in order to reduce the chance of name collisions.

Dennis Williamson
  • 346,391
  • 90
  • 374
  • 439