|
|
|
|
|
by xelxebar
2167 days ago
|
|
This reminds me of a nice sed one-liner I recently happened to craft. Do you ever collect families of functions in your shell scripts under different sections? Here's a nice way of printing out all the functions under a given section: funs(){ sed -n '/^## /h;x;/'"$1"'/{x;s/^\(\w\+\)().*/\1/p;x};x' "$0";}
Where "sections" are delimited by comments of the form "## Section Name" at the beginning of a line. A particularly nice use case is when you write scripts that expect "subcommand" arguments, like $ foo.sh bar baz
and wish to keep track of the available subcommands in the help documentation. Simply collect all your subcommands under the heading "## Subcommands" and stick a funs call in your documentation: usage=$(cat <<USAGE
Usage: foo <subcommand>
Subcommands: $(funs Subcommands)
USAGE
)
The sed one-liner above uses the oft-ignored "hold space" which lets you store data that persists between lines. Here's the same sed but expanded with comments: funs(){ sed -n '/^## /h # Store header line in hold space
x # Swap out current line with header in hold space.
/'"$1"'/{ # Run block if last encountered header matches $1
x # Return to processing current line (instead of header)
s/^\(\w\+\)().*/\1/p # Print function names
x # Whether or not this block runs, we want to return to
# processing the current line. If the block does not
# run, then the hold space contains our current line
# with the active line being our header. So we must
} # return to that state as whell when the block is run.
x # Restore current line from hold space' "$0"
}
|
|