Skip to content

Instantly share code, notes, and snippets.

@julienetie
Last active July 9, 2025 10:20
Show Gist options
  • Save julienetie/e79c5641ee82636b01d914acf172ae97 to your computer and use it in GitHub Desktop.
Save julienetie/e79c5641ee82636b01d914acf172ae97 to your computer and use it in GitHub Desktop.
Enables a file to use template placeholders to be replaced by variables.
#!/bin/bash
# **Example**
# tree="orange"
# live="house"
# sport="football"
# vehicle="car"
# drive="true"
#
# I live in a {{ live }}.
# My tree is an {{ tree }} tree.
# I like {{ sport }}.
# I drive a {{ vehicle }}.
# Driving enabled: {{ drive }}.
# Number of pets: {{ pets }}.
#
# ./define.sh test.txt \
# live s house \
# tree s orange \
# sport s baseball \
# vehicle s car \
# drive b true \
# pets n 3
#
# <selector> <type> <value>
# Check file path provided
if [ $# -lt 1 ]; then
echo "Error: Missing file path argument." >&2
echo "Usage: $0 filepath [selector type value]..." >&2
exit 1
fi
filepath="$1"
shift
# Check file exists
if [ ! -f "$filepath" ]; then
echo "Error: File not found: $filepath" >&2
exit 2
fi
# Check args count divisible by 3 (selector, type, value)
if (( $# % 3 != 0 )); then
echo "Error: Arguments after file path must be in triples: selector type value" >&2
echo "You provided $# extra arguments, which is not divisible by 3." >&2
exit 4
fi
content=$(cat "$filepath")
error_count=0
while [ $# -gt 2 ]; do
selector="$1"
type="$2"
value="$3"
# Validate type & value
case "$type" in
n)
if ! [[ "$value" =~ ^-?[0-9]+(\.[0-9]+)?$ ]]; then
echo "Error: Selector '$selector' expects a number but got '$value'" >&2
error_count=$((error_count + 1))
fi
;;
s)
# Strings: accept anything (no spaces expected)
;;
b)
if ! [[ "$value" =~ ^(true|false|1|0|yes|no)$ ]]; then
echo "Error: Selector '$selector' expects a boolean (true|false|1|0|yes|no) but got '$value'" >&2
error_count=$((error_count + 1))
fi
;;
*)
echo "Error: Unknown type '$type' for selector '$selector'" >&2
error_count=$((error_count + 1))
;;
esac
# If no error, replace all occurrences of {{ selector }} in content
if [ $error_count -eq 0 ]; then
esc_value=$(printf '%s\n' "$value" | sed 's/[&/\]/\\&/g')
content=$(echo "$content" | sed -E "s/\{\{\s*$selector\s*\}\}/$esc_value/g")
fi
shift 3
done
if [ $error_count -gt 0 ]; then
echo "Aborting due to $error_count error(s)." >&2
exit 3
fi
echo "$content" > "$filepath"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment