Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@kovetskiy
Created July 7, 2020 19:01
Show Gist options
  • Save kovetskiy/a4bb510595b3a6b17bfd1bd9ac8bb4a5 to your computer and use it in GitHub Desktop.
Save kovetskiy/a4bb510595b3a6b17bfd1bd9ac8bb4a5 to your computer and use it in GitHub Desktop.
#!/bin/bash
###
### my-script — does one thing well
###
### Usage:
### my-script <input> <output>
###
### Options:
### <input> Input file to read.
### <output> Output file to write. Use '-' for stdout.
### -h Show this message.
help() {
sed -rn 's/^### ?//;T;p' "$0"
}
if [[ $# == 0 ]] || [[ "$1" == "-h" ]]; then
help
exit 1
fi
echo Hello World
@SuperSandro2000
Copy link

SuperSandro2000 commented Jul 8, 2020

Compacted:
[[ $# == 0 || "$1" == "-h" ]]

@evandrix
Copy link

evandrix commented Jul 8, 2020

This doesn't actually work cross-platform, the -r option does not exist on macOS. You can do the same with awk though, just use:

awk '/^###/' "$0"

Complete script:

#!/bin/bash
###
### my-script — does one thing well
###
### Usage:
###   my-script <input> <output>
###
### Options:
###   <input>   Input file to read.
###   <output>  Output file to write. Use '-' for stdout.
###   -h        Show this message.

help() {
    awk '/^###/' "$0"
}

if [[ $# == 0 ]] || [[ "$1" == "-h" ]]; then
    help
    exit 1
fi

echo Hello World

or you can use gsed, if you don't want to pollute the macos sed namespace

@bobrippling
Copy link

A sh compatible version, with portable sed usage

#!/bin/sh
###
### my-script — does one thing well
###
### Usage:
###   my-script <input> <output>
###
### Options:
###   <input>   Input file to read.
###   <output>  Output file to write. Use '-' for stdout.
###   -h        Show this message.

help() {
    sed -n 's/^### \?//p' "$0"
}

if [ $# -eq 0 ] || [ "$1" = "-h" ]; then
    help
    exit 1
fi

echo Hello World

@NightMachinery
Copy link

NightMachinery commented Jul 8, 2020

Complete awk version:

#!/usr/bin/env bash
###
### my-script — does one thing well
###
### Usage:
###   my-script <input> <output>
###
### Options:
###   <input>   Input file to read.
###   <output>  Output file to write. Use '-' for stdout.
###   -h        Show this message.

help() {
    awk -F'### ' '/^###/ { print $2 }' "$0"
}

if [[ $# == 0 || "$1" == "-h" ]]; then
    help
    exit 1
fi

echo Hello World

I personally use macros to add help messages to my zsh functions. It's as easy as:

mdoc-test() {
	# uses the global alias MAGIC
    mdoc Usage: sth MAGIC
    echo no
}
mdoc-test2() {
	# without global alias
    magic mdoc Usage: sth ; mret
    echo no
}

@rmNyro
Copy link

rmNyro commented Jul 8, 2020

Awesome idea, thanks very much!

@james-see
Copy link

Very cool.

Copy link

ghost commented Jul 12, 2020

That's a good idea. Awesome!

@jc00ke
Copy link

jc00ke commented Jul 12, 2020

@typebrook
Copy link

typebrook commented Jul 17, 2020

Glad someone proved this is a good strategy to write helper message, I also did it in my commonly-used script:
https://gist.github.com/typebrook/b0d2e7e67aa50298fdf8111ae7466b56#file-gist

what I did is simply print the comment at the top(except the first line to # --):
sed -Ene "/^#/ !q; 1,/^# --/ d; s/^# //p

@kovetskiy
@benhutchins

This doesn't actually work cross-platform, the -r option does not exist on macOS. You can do the same with awk though, just use:

-E works on BSD sed, so you can make it portable with sed -Ene 's/^### ?//;T;p' "$0" both on mac(BSD sed) or Linux(GNU sed).

@Qbin
Copy link

Qbin commented Jul 24, 2020

666

@snejus
Copy link

snejus commented Oct 15, 2020

Why even use the extended version?

sed -n 's/^###//p' achieves the same. Just keep the leading ### format to the help only.

sed -n '/^###/ s///p' this one's faster but a tiny bit more verbose.

and sed '/^###/!d' if you don't mind hashes. Or grep "^###"

@ivant
Copy link

ivant commented Nov 29, 2023

My version, that doesn't require multiple # (but allows more than one if you want it for stylistic reasons):

#!/bin/bash
# Usage:
#   test_usage.sh ...

print_usage_and_exit() {
  # The sed script below:
  # - Deletes the first line (shebang).
  # - Quits on the first line that doesn't start with #.
  # - Removes the '#+ ?' prefix from the string.
  sed -En '1d; /^[^#]/ q; s/^#+ ?//p;' < "$0" >&2
  exit 1
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment