Skip to content

Instantly share code, notes, and snippets.

@ephrin
Last active December 3, 2023 11:52
Show Gist options
  • Save ephrin/32cb80b386537b82763466a4d36313b6 to your computer and use it in GitHub Desktop.
Save ephrin/32cb80b386537b82763466a4d36313b6 to your computer and use it in GitHub Desktop.
eval and substitute from prototype env file
#!/bin/bash
# Default values for source and output files
env_example=".env.example"
env_output=".env"
# Flag to ask for confirmation for each variable (enabled by default)
ask_each_var=1
# Function to display help message
display_help() {
echo "Usage: $0 [OPTIONS]"
echo
echo "Options:"
echo " -h, --help Show this help message and exit."
echo " -q, --quiet Run without asking for confirmation for each variable."
echo " -s, --source Specify the source file. Default is '.env.example'."
echo " -o, --output Specify the output file. Default is '.env'."
echo
echo "This script processes a source environment file (.env.example by default),"
echo "updating or adding its variables to a destination environment file (.env by default)."
echo "It supports command substitution and environment variable expansion."
echo
}
# Process script arguments
while [[ "$#" -gt 0 ]]; do
case $1 in
-h|--help)
display_help
exit 0
;;
-q|--quiet)
ask_each_var=0
;;
-s|--source)
env_example="$2"
shift
;;
-o|--output)
env_output="$2"
shift
;;
*)
echo "Unknown option: $1"
display_help
exit 1
;;
esac
shift
done
# Check if the source file exists
if [ ! -f "$env_example" ]; then
echo "Source file $env_example does not exist."
exit 1
fi
# Create the output file if it doesn't exist
if [ ! -f "$env_output" ]; then
touch "$env_output"
fi
# Function to ask for confirmation, showing current and new values
ask_confirmation() {
current_value=$2
new_value=$3
while true; do
read -p "Variable '$1' has value '$current_value'. Replace with new value '$new_value'? [y/n] " yn < /dev/tty
case $yn in
[Yy]* ) return 0;;
[Nn]* ) return 1;;
* ) echo "Please answer yes or no.";;
esac
done
}
# Read current .env file into an associative array
declare -A env_vars
while IFS='=' read -r key value; do
env_vars["$key"]="$value"
done < "$env_output"
# Process each line from .env.example
while IFS='=' read -r key value; do
# Replace command substitution and environment variable expansion
new_value=$(eval "echo $value")
# Check if the key already exists in the destination file
if [[ "${env_vars[$key]+isset}" ]]; then
# Read the existing value from the destination file
current_value="${env_vars[$key]}"
# Check if we should ask for confirmation and if the values are different
if [[ $ask_each_var -eq 1 && "$current_value" != "$new_value" ]]; then
ask_confirmation "$key" "$current_value" "$new_value" && env_vars["$key"]="$new_value"
else
env_vars["$key"]="$new_value"
fi
else
# If the key is not in the existing file, add it
env_vars["$key"]="$new_value"
fi
done < "$env_example"
# Write the .env file
> "$env_output"
for key in "${!env_vars[@]}"; do
echo "$key=${env_vars[$key]}" >> "$env_output"
done
echo "Updated .env file:"
cat "$env_output"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment