2
\$\begingroup\$

The build.sbt text file contains versions like this:

name := "happy"
scalaVersion := "2.11.8"
sparkVersion := "2.2.0"

I wrote a Bash script to parse out the PROJECT_NAME and SCALA_VERSION from the build.sbt file:

PROJECT_NAME=$(cat build.sbt | grep "name :=" | cut -f 3 -d " " | tr -d '"')
SCALA_VERSION=$(cat build.sbt | grep "scalaVersion :=" | cut -f 3 -d " " | tr -d '"')

How can I write this more elegantly / robustly? I'm ok with an awk or sed approach, but don't want to add an external dependency to the script.

Here's some more of the script to see how the variables are being used.

if [ "$SCALA_VERSION" = "" ]
  then
    echo "SCALA_VERSION variable cannot be empty"
    exit 1
fi

SCALA_BINARY_VERSION=${SCALA_VERSION%.*}
if [ "$SCALA_BINARY_VERSION" = "" ]
  then
    echo "SCALA_BINARY_VERSION variable cannot be empty"
    exit 1
fi

echo "Create a GitHub release"
JAR_PATH=target/scala-${SCALA_BINARY_VERSION}/${PROJECT_NAME}_${SCALA_BINARY_VERSION}-${SPARK_VERSION}_${PROJECT_VERSION}.jar
hub release create -a $JAR_PATH -m "Release v${PROJECT_VERSION}" v${PROJECT_VERSION}
\$\endgroup\$
  • \$\begingroup\$ Could you also show more of the Bash script, where you use the variables? \$\endgroup\$ – 200_success Nov 9 '17 at 6:08
  • 1
    \$\begingroup\$ @200_success - Sure, I updated the post to show more of the script, thanks. \$\endgroup\$ – Powers Nov 9 '17 at 14:48
2
\$\begingroup\$

If you don't mind spinning up sbt to extract the settings keys you could use the following:

PROJECT_NAME="$(sbt name | tail -1)"
PROJECT_NAME="${PROJECT_NAME#* }"

SCALA_VERSION="$(sbt scalaVersion | tail -1)"
SCALA_VERSION="${SCALA_VERSION#* }"

echo $PROJECT_NAME
echo $SCALA_VERSION
\$\endgroup\$
  • \$\begingroup\$ sbt -no-colors name is even better to remove ANSI color codes from the text stream \$\endgroup\$ – Powers Nov 10 '17 at 0:25
2
\$\begingroup\$

I'd use awk to generate shell syntax, and source it in the shell:

$ source <(
    awk '
        $1 == "name"         {print "PROJECT_NAME=" $NF}
        $1 == "scalaVersion" {print "SCALA_VERSION=" $NF}
    ' build.sbt
)

$ echo $PROJECT_NAME,$SCALA_VERSION
happy,2.11.8

If the name or version strings might contain spaces, then we need to be more specific about awk's field separator:

$ cat build.sbt
name := "hello world"
scalaVersion := "2.11.8"
sparkVersion := "2.2.0"

$ awk '
    $1 == "name"         {print "PROJECT_NAME=" $NF}
    $1 == "scalaVersion" {print "SCALA_VERSION=" $NF}
' build.sbt

PROJECT_NAME=world"              # << oops
SCALA_VERSION="2.11.8"

$ awk -F '"' '
    $1 ~ /^name/         {printf "PROJECT_NAME=\"%s\"\n",  $2}
    $1 ~ /^scalaVersion/ {printf "SCALA_VERSION=\"%s\"\n", $2}
' build.sbt

PROJECT_NAME="hello world"
SCALA_VERSION="2.11.8"
\$\endgroup\$
0
\$\begingroup\$

No one else has mentioned this, so I’ll add it here. There is no need to cat file | grep pattern. I might do it in an interactive shell if I forget which parameter is which, but for a script it is needless.

In

PROJECT_NAME=$(cat build.sbt | grep "name :=" | cut -f 3 -d " " | tr -d '"')
SCALA_VERSION=$(cat build.sbt | grep "scalaVersion :=" | cut -f 3 -d " " | tr -d '"')

prefer grep file pattern usage. Grep can read the file for you; no need for cat and a pipe.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.