Java Programming Tutorials

Java programming tutorials with many code examples!

Bash Here Documents

Problem:

How to create Here/inline Documents in Bash?

Bash Here documents can be really helpful templating mechanism when used in Bash scripts. They can generate almost anything, even scripts to compile and run sample Java code!

Solution:

The syntax of Bash here documents is simple:

# "<<" or "<<-"
<<[-]word
    here-document content
delimiter

How it works: When Bash sees “<<WORD” the it knows that it is a Here Document and reads everything until it finds “WORD” on a single line. If the operator is “<<-WORD” then it removes all leading TAB chars from the input.

For some commands you can just pass read input, but very often its useful to redirect the input to some file using “>>” operator, like in the example below.

Here’s an example of a shell script that takes a package and class name and generates package with sample Java class content:

#!/bin/bash

if [ $# -eq 0 ]; then
    echo "Usage: $0 package class"
    echo
    echo "Creates a Java class within specified package."
    echo "Example: $0 com.farenda.solved JavaExampleClass"
    exit 1
fi

PACKAGE="${1}"
PACKAGE_DIR="${PACKAGE//.//}"
MAIN_CLASS="${2}"

echo "Creating Java package dirs: ${PACKAGE_DIR}"
mkdir -p "${PACKAGE_DIR}"

# read until EOF and redirect to the new Java class:
cat <<EOF >> "${PACKAGE_DIR}/${MAIN_CLASS}.java"
package ${PACKAGE};

public class ${MAIN_CLASS} {
    public static void main(String[] args) {
        System.out.println("Hello, world!");
    }
}
EOF

PACKAGE_DIR var is created using Bash variable substitution. The expression ${PACKAGE//.//} means: take value of PACKAGE variable and substitute all dots . with /, to turn Java package name into a path on a filesystem.

You can use any word you like as a delimiter, but EOF is commonly used.

If you want, you can extend the shell script with generation of Java compilation script, like so:

COMPILER=compile.sh
echo "Creating compilation script: ${COMPILER}"
cat <<EOF >> ${COMPILER}
#!/bin/bash
echo "Compiling: javac ${PACKAGE_DIR}/*.java"
javac ${PACKAGE_DIR}/*.java
EOF
chmod u+x ${COMPILER}

echo
echo "To compile code execute: ./${COMPILER}"

You can use Bash variable substitution in Here Documents and automate generation of many, many things.

Lets run it to see how it all work:

$> ./here-documents.sh com.farenda.solved SampleClass
Creating Java package dirs: com/farenda/solved
Creating compilation script: compile.sh

To compile code execute: ./compile.sh
$> ./compile.sh
Compiling: javac com/farenda/solved/*.java
$> java -cp . com.farenda.solved.SampleClass
Hello, world!

Isn’t that cool? :-)

Share with the World!