This is part 1 of a series of quick and dirty tricks I’ve used in various scripts over the years. In this post, I’ll show how I like to provide help text for shell scripts.

In this example, the script can be called with -h or --help to print the help text:

#!/usr/bin/env bash
# Usage: my-script
#
# my-script is kind of good
#
# EXAMPLES
#
# This is the way we use my-script:
#   $ my-script
# 
# Or I guess you could use it like this:
#   $ my-script --hi

# Print help text and exit.
if [[ "$1" = "-h" ]] || [[ "$1" = "--help" ]]; then
  sed -ne '/^#/!q;s/.\{1,2\}//;1d;p' < "$0"
  exit
fi

# The actual script goes here
echo "$@"

Running my-script --help (or -h) outputs:

Usage: my-script

my-script is kind of good

EXAMPLES

This is the way we use my-script:
  $ my-script

Or I guess you could use it like this:
  $ my-script --hi

The special sauce here is sed -ne '/^#/!q;s/.\{1,2\}//;1d;p' < "$0". Broken down:

sed -ne '...' < "$0"

Run the sed (stream editor) utility. The -n switch disables the default output behavior, The -e '...' switch specifies sed commands to be run. < "$0" means that sed will operate on the script itself — in this case it will parse the script to print just the help text.

The actual sed commands (/^#/!q;s/.\{1,2\}//;1d;p) are actually 4 separate commands separated by ;: /^#/!q, s/.\{1,2\}//, 1d and p. Here’s what each does.

/^#/!q

Match lines that start with #. When one is encountered that does NOT start with #, stop looking for matching lines. This allows you to have additional comments in your script without having them appear in the help text.

s/.\{1,2\}//

Replace the first two characters in each matched line with an empty string (i.e. delete them).

1d

Delete the first line from the matched text. This is the script’s shebang and is not part of the help text.

p

Print the remaining lines.