Skip to content

Instantly share code, notes, and snippets.

@LoganGray
Last active September 27, 2024 01:29
Show Gist options
  • Save LoganGray/d9111c3a882ad5e4c37a6a8576733ef7 to your computer and use it in GitHub Desktop.
Save LoganGray/d9111c3a882ad5e4c37a6a8576733ef7 to your computer and use it in GitHub Desktop.
a somewhat supercharged configuration changer/add-er. If someone out there knows something better - please let me know! ;) Seems like this should already exist
#!/bin/bash
#set-conf bash thing
# for setting a configuration setting in a file defaulting with a : colon assignment
# and adds the setting if it doesn't find it.
#
#setconf <filepath&name> "string" "<setting>" [-y]
#i.e. setconf.sh /etc/datadog/datadog.yaml "api_key" "your_api_key_here" -y
# Color and formatting definitions
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
LIGHT_BLUE='\033[1;34m'
BLUE='\033[0;34m'
BOLD='\033[1m'
NC='\033[0m' # No Color
function echo_color() {
local color="$1"
local message="$2"
local bold=${3:-false}
if [ "$bold" = true ]; then
echo -e "${color}${BOLD}${message}${NC}"
else
echo -e "${color}${message}${NC}"
fi
}
function print_boxed_output() {
local line1="$1"
local line2="$2"
local line3="$3"
local line4="$4"
local width=80
local horizontal_line=$(printf '%*s' "$width" | tr ' ' '-')
echo -e "${LIGHT_BLUE}+${horizontal_line}+${NC}"
printf "${LIGHT_BLUE}|${NC} %-76s ${LIGHT_BLUE}|${NC}\n" "$line1"
printf "${LIGHT_BLUE}|${NC} %-76s ${LIGHT_BLUE}|${NC}\n" "$line2"
printf "${LIGHT_BLUE}|${NC} %-76s ${LIGHT_BLUE}|${NC}\n" "$line3"
printf "${LIGHT_BLUE}|${NC} %-76s ${LIGHT_BLUE}|${NC}\n" "$line4"
echo -e "${LIGHT_BLUE}+${horizontal_line}+${NC}"
}
function spinner() {
local pid=$1
local delay=0.1
local spinstr='|/-\'
while [ "$(ps a | awk '{print $1}' | grep $pid)" ]; do
local temp=${spinstr#?}
printf " [%c] " "$spinstr"
local spinstr=$temp${spinstr%"$temp"}
sleep $delay
printf "\b\b\b\b\b\b"
done
printf " \b\b\b\b"
}
function detect_separator() {
local file="$1"
local colon_count=0
local equals_count=0
while IFS= read -r line; do
# Skip empty lines
[[ -z "$line" ]] && continue
# Remove URLs from the line before counting colons
local line_without_urls=$(echo "$line" | sed -E 's|https?://[^[:space:]]+||g')
# Count occurrences of : and = with potential surrounding spaces
colon_count=$((colon_count + $(echo "$line_without_urls" | grep -oE '\s*:\s*' | wc -l)))
equals_count=$((equals_count + $(echo "$line" | grep -oE '\s*=\s*' | wc -l)))
done < "$file"
echo "Colon count (excluding URLs): $colon_count" >&2
echo "Equals sign count: $equals_count" >&2
# Determine the more common separator
if [[ $colon_count -gt $equals_count ]]; then
echo " : "
elif [[ $equals_count -gt $colon_count ]]; then
echo " = "
else
# If counts are equal, default to colon
echo " : "
fi
}
function create_backup() {
local file="$1"
local backup_file="${file}.$(date +%Y%m%d_%H%M%S).bak"
cp "$file" "$backup_file"
echo "Backup created: $backup_file"
}
function replace-line-in-file() {
local file="$1"
local line_num="$2"
local setting="$3"
local settingvalue="$4"
local separator="$5"
local non_interactive="$6"
local replacement="${setting}${separator}${settingvalue}"
# Get the current line content
local current_line=$(sed -n "${line_num}p" "$file")
echo_color $YELLOW "Current value: $current_line" true
echo_color $GREEN "New value: $replacement" true
if [[ "$non_interactive" != "true" ]]; then
# Prompt for confirmation
read -p "Do you want to proceed with this change? (y/n): " confirm
if [[ $confirm != [yY] ]]; then
echo "Change aborted."
exit 0
fi
fi
# Create backup
create_backup "$file"
# Escape backslash, forward slash and ampersand for use as a sed replacement.
replacement_escaped=$(echo "$replacement" | sed -e 's/[\/&]/\\&/g')
sed -i "${line_num}s/.*/${replacement_escaped}/" "$file"
echo "Change applied successfully."
}
FILENAME="$1"
STRING2CK4="$2"
SETTINGVALUE="$3"
NON_INTERACTIVE="false"
# Check if the last argument is -y
if [[ "${!#}" == "-y" ]]; then
NON_INTERACTIVE="true"
# Remove the last argument
set -- "${@:1:$#-1}"
fi
if [[ -z $FILENAME || -z $STRING2CK4 || -z $SETTINGVALUE ]]; then
echo "all parameters must be passed!"
echo "ex."
echo "setconf.sh <filename & path> <String to search for> <value to set to> [-y]"
exit 1
fi
#TODO: test if permission / access to file exists
# Print the first 4 lines in a box
print_boxed_output \
"Filename: $FILENAME" \
"STRING2CK4: $STRING2CK4" \
"SETTINGVALUE: $SETTINGVALUE" \
"Non-interactive mode: $NON_INTERACTIVE"
# Detect the separator used in the file
echo_color $YELLOW "Notice: Separator detection may take some time for large files." true
echo_color $BLUE "Detecting separators..." false
# Run detect_separator in the background and capture its PID
detect_separator "$FILENAME" > /tmp/separator_result.txt &
DETECT_PID=$!
# Run the spinner while detect_separator is running
spinner $DETECT_PID
# Read the result from the temporary file
SEPARATOR=$(cat /tmp/separator_result.txt)
rm /tmp/separator_result.txt # Clean up the temporary file
echo "Detected separator: '$SEPARATOR'"
LINE2RPL=$(grep -n -m 1 "$STRING2CK4" "$FILENAME" | sed 's/\([0-9]*\).*/\1/')
if [ -z "$LINE2RPL" ]; then
echo "line2RPL is blank - item not found - prepare to insert at end of file!"
echo "New value to be added: ${STRING2CK4}${SEPARATOR}${SETTINGVALUE}"
if [[ "$NON_INTERACTIVE" != "true" ]]; then
# Prompt for confirmation
read -p "Do you want to proceed with adding this new line? (y/n): " confirm
if [[ $confirm != [yY] ]]; then
echo "Addition aborted."
exit 0
fi
fi
# Create backup
create_backup "$FILENAME"
# Add the new line
echo "${STRING2CK4}${SEPARATOR}${SETTINGVALUE}" >> "$FILENAME"
echo "New line added successfully."
else
echo "line2RPL is set to '$LINE2RPL' - preparing to replace!";
replace-line-in-file "$FILENAME" "$LINE2RPL" "$STRING2CK4" "$SETTINGVALUE" "$SEPARATOR" "$NON_INTERACTIVE"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment