Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
#!/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
@zouhair
Copy link

zouhair commented Jul 7, 2020

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

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

@brucewoodward
Copy link

brucewoodward commented Jul 7, 2020

That's cool but I think I'll stick with here documents.

#!/bin/bash

Help=$(cat <<-"HELP"

 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
)

help() {
    echo "$Help"
}

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

echo Hello World

@jdugan1024
Copy link

jdugan1024 commented Jul 7, 2020

This is a really nifty approach, thanks for sharing. It's fairly obvious in retrospect but it hadn't occurred to me before!

Slight tweak, this awk solution will only print the help text, not the leading ### :

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

@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

bobrippling commented Jul 8, 2020

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!

@constantskeptic
Copy link

constantskeptic commented Jul 9, 2020

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 "^###"

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