Skip to content

Instantly share code, notes, and snippets.

@robCrawford
Last active June 11, 2024 10:55
Show Gist options
  • Save robCrawford/7191064efc765c47be7d1b963be05008 to your computer and use it in GitHub Desktop.
Save robCrawford/7191064efc765c47be7d1b963be05008 to your computer and use it in GitHub Desktop.
#!/usr/bin/env zsh
# Replace strings in a source file from an array of replacements
# The output file is named with `-edit` appended e.g. `src-edit.txt`
# Example:
# `replace-array src.txt replacements.sh --verbose`
# - The first file is the source
# - The second file defines single and global replacement arrays e.g.
# ```
# #!/usr/bin/env zsh
# replaceOnce=("find" "replace" "find" "replace")
# replaceGlobal=("find" "replace" "find" "replace")
# ```
# - The `-v` or `--verbose` flag logs debug
declare -A _REPLACE_ARRAY_SINGLE_FAILS
declare -A _REPLACE_ARRAY_GLOBAL_FAILS
replace-array() {
local srcFile="$1"
local arraysFile="$2"
local singleFails=0
local globalFails=0
local verbose
local red='\033[0;31m'
local reset='\033[0m'
local i
zparseopts -D -E -F -K {v,-verbose}=verbose
if [ ! -f "$srcFile" ] || [ ! -f "$arraysFile" ]; then
echo "Usage: replace-array src.txt replacements.sh"
return
fi
local output=$(<"$srcFile")
source "$arraysFile"
if [ -v replaceOnce ]; then
for (( i=1; i<${#replaceOnce[@]}; i+=2 )); do
local onceInput="$output"
local onceOutput="${onceInput/${replaceOnce[i]}/${replaceOnce[i+1]}}"
if [ "$onceOutput" = "$onceInput" ]; then
(( singleFails++ ))
if (( $#verbose )); then
echo -e "${red}Single replacement failed:${reset}"
echo -e "'$replaceOnce[i]'\n"
fi
fi
output="$onceOutput"
done
fi
if [ -v replaceGlobal ]; then
for (( i=1; i<${#replaceGlobal[@]}; i+=2 )); do
local globalInput="$output"
local globalOutput="${globalInput//${replaceGlobal[i]}/${replaceGlobal[i+1]}}"
if [ "$globalOutput" = "$globalInput" ]; then
(( globalFails++ ))
if (( $#verbose )); then
echo -e "${red}Global replacement failed:${reset}"
echo -e "'$replaceGlobal[i]'\n"
fi
fi
output="$globalOutput"
done
fi
if [ -v replaceOnce ]; then
if [ "$singleFails" -gt "$_REPLACE_ARRAY_SINGLE_FAILS[$arraysFile]" ]; then
echo -e "${red}❌ New single replacements failed: $((singleFails - _REPLACE_ARRAY_SINGLE_FAILS[$arraysFile]))${reset}"
fi
_REPLACE_ARRAY_SINGLE_FAILS[$arraysFile]=$singleFails
fi
if [ -v replaceGlobal ]; then
if [ "$globalFails" -gt "$_REPLACE_ARRAY_GLOBAL_FAILS[$arraysFile]" ]; then
echo -e "${red}❌ New global replacements failed: $((globalFails - _REPLACE_ARRAY_GLOBAL_FAILS[$arraysFile]))${reset}"
fi
_REPLACE_ARRAY_GLOBAL_FAILS[$arraysFile]=$globalFails
fi
echo "$output" > "${srcFile:r}-edit.${srcFile:e}"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment