Last active
February 4, 2022 17:18
-
-
Save bermi/a3f2327e0abd3c722a7194287fe5204d to your computer and use it in GitHub Desktop.
Simple bash and sed templating using delimiters.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# Simple bash and sed templating using delimiters. | |
# | |
# For example, given a template /template-a with the contents | |
# | |
# # This is template A | |
# # | |
# ### EXAMPLE_TEMPLATE_BEGIN | |
# echo "Hello from template A" | |
# ### EXAMPLE_TEMPLATE_END | |
# # | |
# # Anything before or after the delimiters is ignored | |
# | |
# And a file /file-name with the contents | |
# | |
# echo "Some text already on /file-name" | |
# | |
# The following command | |
# | |
# template append EXAMPLE /template-a </file-name | |
# | |
# will generate the following output | |
# | |
# echo "Some text already on /file-name" | |
# ### EXAMPLE_TEMPLATE_BEGIN | |
# echo "Hello from template A" | |
# ### EXAMPLE_TEMPLATE_END | |
# | |
# calling the command `template append EXAMPLE /template-a </file-name` again will | |
# not append the template again. | |
# | |
# To remove the template call: | |
# | |
# template strip EXAMPLE </file-name | |
# | |
# To prepend the template call: | |
# | |
# template prepend EXAMPLE /template-a </file-name | |
# | |
# To replace the template call: | |
# | |
# template replace EXAMPLE /template-a </file-name | |
# | |
# To inject a template at a '### TEMPLATE_EXAMPLE_PLACEHOLDER' call: | |
# | |
# template inject EXAMPLE /template-a </file-name | |
# | |
# Note: anything outside _BEGIN / _END tags will be ignored. | |
# Limitations: | |
# - Only one template with the same name per file. | |
# - No support for evaluating variables. Use envsubst for that purpose. | |
# | |
# Author: Bermi Ferrer | |
# License: MIT | |
# Code and bugs: https://gist.github.com/bermi/a3f2327e0abd3c722a7194287fe5204d | |
# | |
set -eEuo pipefail | |
shopt -s inherit_errexit | |
IFS=$'\n\t' | |
get_template() { | |
set -eEuo pipefail; | |
local template_name="${1:?You must provide a template name}" | |
template_name="$(echo -n "$template_name" | tr '[:lower:]' '[:upper:]' | tr '-' '_')" | |
local template | |
template="$(cat)" | |
if [ "$(echo "$template" | grep -c "### ${template_name}_TEMPLATE_BEGIN")" != "1" ]; then | |
echo "Error: template must contain exactly one '### ${template_name}_TEMPLATE_BEGIN' delimiter" >&2 | |
exit 1 | |
fi | |
if [ "$(echo "$template" | grep -c "### ${template_name}_TEMPLATE_END")" != "1" ]; then | |
echo "Error: template must contain exactly one '### ${template_name}_TEMPLATE_END' delimiter" >&2 | |
exit 1 | |
fi | |
echo "$template" | sed -n "/^[ ]*### ${template_name}_TEMPLATE_BEGIN/,\${p;/^[ ]*### ${template_name}_TEMPLATE_END/q}" | |
} | |
strip_template() { | |
set -eEuo pipefail; | |
local template_name="${1:?You must provide a template name}" | |
template_name="$(echo -n "$template_name" | tr '[:lower:]' '[:upper:]' | tr '-' '_')" | |
local template | |
template="$(cat)" | |
echo "$template" | sed "/^[ ]*### ${template_name}_TEMPLATE_BEGIN/,/^[ ]*### ${template_name}_TEMPLATE_END/d" | |
} | |
append_template() { | |
set -eEuo pipefail; | |
local template_name="${1:?You must provide a template name}" | |
local template_path="${2:?You must provide a path to the template file}" | |
strip_template "$1" | cat - <(echo "") <(get_template "$template_name" <"$template_path") | |
} | |
prepend_template() { | |
set -eEuo pipefail; | |
local template_name="${1:?You must provide a template name}" | |
local template_path="${2:?You must provide a path to the template file}" | |
get_template "$template_name" <"$template_path"; | |
strip_template "$1"; | |
} | |
replace_template() { | |
set -eEuo pipefail; | |
local template_name="${1:?You must provide a template name}" | |
template_name="$(echo -n "$template_name" | tr '[:lower:]' '[:upper:]' | tr '-' '_')" | |
local template_path="${2:?You must provide a path to the template file}" | |
# get_template "$template_name" <"$template_path"; | |
# strip_template "$1"; | |
sed -E "s/([ ]*### ${template_name}_TEMPLATE_BEGIN)/### TEMPLATE_${template_name}_PLACEHOLDER\n\1/" | \ | |
sed "/^[ ]*### ${template_name}_TEMPLATE_BEGIN/,/^[ ]*### ${template_name}_TEMPLATE_END/d" | |
} | |
inject_template() { | |
set -eEuo pipefail; | |
local template_name="${1:?You must provide a template name}" | |
template_name="$(echo -n "$template_name" | tr '[:lower:]' '[:upper:]' | tr '-' '_')" | |
local template_path="${2:?You must provide a path to the template file}" | |
local placeholder="### TEMPLATE_${template_name}_PLACEHOLDER" | |
local rendered_template_path | |
rendered_template_path=$(mktemp) | |
get_template "$template_name" <"$template_path" >"$rendered_template_path" | |
sed "/${placeholder}/e cat '$rendered_template_path'" | sed "/${placeholder}/d" | |
rm -rf "$rendered_template_path" | |
} | |
if [ "${1:-false}" != "false" ]; then | |
if [ "$1" = "append" ]; then | |
shift | |
append_template "${1:?You must provide a template name}" "${2:?You must provide a path to the template file}" | |
elif [ "$1" = "prepend" ]; then | |
shift | |
prepend_template "${1:?You must provide a template name}" "${2:?You must provide a path to the template file}" | |
elif [ "$1" = "inject" ]; then | |
shift | |
inject_template "${1:?You must provide a template name}" "${2:?You must provide a path to the template file}" | |
elif [ "$1" = "replace" ]; then | |
shift | |
replace_template "${1:?You must provide a template name}" "${2:?You must provide a path to the template file}" | |
elif [ "$1" = "strip" ]; then | |
shift | |
strip_template "${1:?You must provide a template name}" | |
elif [ "$1" = "get" ]; then | |
shift | |
get_template "${1:?You must provide a template name}" | |
else | |
echo "Error: Invalid method $1. Valid method are: append, strip and get" >&2 | |
exit 1 | |
fi | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment