Created
June 23, 2022 13:29
-
-
Save stekern/23e4804c0801520b50c0c3e5b3822138 to your computer and use it in GitHub Desktop.
Shell script for replacing placeholders in files in a portable-ish manner
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 | |
# | |
# Helper functions for replacing placeholders in files. | |
# | |
# Distributed under terms of the MIT license. | |
set -euo pipefail | |
IFS=$'\n\t' | |
# Print example usage of the script. | |
usage() { | |
local script_name script_name="$(printf "%s\n" "$(basename "$0")")" | |
cat <<EOF | |
USAGE: $script_name ACTION [OPTIONS] | |
EXAMPLES: | |
$script_name --my-placeholder-name "my-placeholder-value" | |
EOF | |
exit 0 | |
} | |
# Utility function for asking for confirmation | |
confirm() { | |
local query yn | |
query="$1" | |
while true; do | |
read -rp "$query " yn | |
case $yn in | |
yes ) return 0;; | |
[nN]* ) return 1;; | |
* ) printf "Please answer yes or no.\n";; | |
esac | |
done | |
} | |
# Replace placeholders in a predefined set of files | |
# The characters `<` and `>` are used as delimiters to define a placeholder. | |
# | |
# Append `|strip` to the name of the placeholder (e.g., `<my-placeholder|strip>`) | |
# to remove everything except "standard" characters (alphanumeric, hyphen, underscore or period) in the desired replacement value. | |
# | |
# Append `|lowercase` to the name of the placeholder (e.g., `<my-placeholder|lowercase>`) | |
# to force the desired replacement value to lowercase. | |
replace_placeholders() { | |
local placeholders values search_files timestamp \ | |
i placeholder value f | |
placeholders=() | |
values=() | |
while [ -n "${1:-}" ]; do | |
case "$1" in | |
--*) placeholders+=("${1#"--"}"); shift; if test -n "${1:-}"; then values+=("$1"); shift; else echo "Missing placeholder value"; exit 1; fi;; | |
*) echo "Unknown parameter format '$1'"; exit 1 ;; | |
esac | |
done | |
search_files=() | |
while read -r -d ''; do | |
search_files+=("$REPLY") | |
done < <(find . \( \ | |
-name "node_modules" -prune -false \ | |
-o -wholename "./Jenkinsfile" \ | |
-o -wholename "*/src/config.ts" \ | |
\) -print0) | |
timestamp="$(date +%s)" | |
if [ "${#search_files[@]}" -gt 0 ]; then | |
printf "Found the following files:\n---\n" | |
printf "%s\n" "${search_files[@]}" | |
printf "\n\n" | |
if [ ! "${AUTO_CONFIRM:-false}" = "true" ]; then | |
if ! confirm "Do you want to replace placeholders in these files?"; then | |
exit 1 | |
fi | |
fi | |
fi | |
for i in "${!placeholders[@]}"; do | |
placeholder="${placeholders[i]}" | |
value="${values[i]}" | |
for f in "${search_files[@]}"; do | |
# GNU and FreeBSD sed work in different ways. This command should work for both | |
sed -i."${timestamp}.tmp" \ | |
-e "s/<$placeholder>/$value/g" \ | |
-e "s/<${placeholder}[|]strip>/$(echo "$value" | sed 's/[^a-zA-Z0-9_.-]//g')/g" \ | |
-e "s/<${placeholder}[|]lowercase>/$(echo "$value" | tr '[:upper:]' '[:lower:]')/g" \ | |
"$f" && test -f "$f.$timestamp.tmp" && rm "$f.$timestamp.tmp" | |
done | |
done | |
} | |
main() { | |
if [ $# -eq 0 ]; then | |
usage | |
fi | |
case "$1" in | |
--help) | |
usage | |
;; | |
*) | |
replace_placeholders "$@" | |
;; | |
esac | |
} | |
main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment