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
@TheFox

This comment has been minimized.

Copy link

@TheFox TheFox commented Jul 7, 2020

This. Is. Perfect. 😍

@benhutchins

This comment has been minimized.

Copy link

@benhutchins benhutchins commented Jul 7, 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
@cvega

This comment has been minimized.

Copy link

@cvega cvega commented Jul 7, 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:

Install GNU coreutils and gnu-sed on MacOS using brew install coreutils gnu-sed if you want to get closer to Linux.

@zouhair

This comment has been minimized.

Copy link

@zouhair zouhair commented Jul 7, 2020

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

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

@brucewoodward

This comment has been minimized.

Copy link

@brucewoodward 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

This comment has been minimized.

Copy link

@jdugan1024 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

This comment has been minimized.

Copy link

@SuperSandro2000 SuperSandro2000 commented Jul 8, 2020

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

@evandrix

This comment has been minimized.

Copy link

@evandrix 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

This comment has been minimized.

Copy link

@bobrippling 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
@NightMachinary

This comment has been minimized.

Copy link

@NightMachinary NightMachinary 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

This comment has been minimized.

Copy link

@rmNyro rmNyro commented Jul 8, 2020

Awesome idea, thanks very much!

@jamesacampbell

This comment has been minimized.

Copy link

@jamesacampbell jamesacampbell commented Jul 9, 2020

Very cool.

@haukeng

This comment has been minimized.

Copy link

@haukeng haukeng commented Jul 12, 2020

That's a good idea. Awesome!

@jc00ke

This comment has been minimized.

Copy link

@jc00ke jc00ke commented Jul 12, 2020

@typebrook

This comment has been minimized.

Copy link

@typebrook 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

This comment has been minimized.

Copy link

@Qbin Qbin commented Jul 24, 2020

666

@snejus

This comment has been minimized.

Copy link

@snejus 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
You can’t perform that action at this time.