Last active
November 14, 2023 04:35
-
-
Save loopyd/5161b606188280d955975edbc2785779 to your computer and use it in GitHub Desktop.
[Bash] ini parselib - Bash/perl library for reading/modifying ini files
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
#!/bin/bash | |
# | |
# 📯 * AAAAAAAAAAAAAAAAAAAUUUUUUUUUUUUUUUUHHHHHHNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN!!!! * 📯 | |
# | |
# You didn't ask. I did it anyway. Now as a zero-dependency gulp.sh | |
# | |
# CONTRIBUTIONS? BUGFIXES? UNCONVERED EDGE CASES? Make them known. | |
# | |
# update_ini_file: Updates or adds a key-value pair in a specific section of an INI file | |
# Arguments: | |
# file: The INI file to update | |
# section: The section in the INI file where the key-value pair resides | |
# key: The key to update/add | |
# raw_value: The value to be assigned to the key | |
# comment: Optional comment to be added above the section | |
update_ini_file() { | |
local file=$1 section=$2 key=$3 raw_value=$4 comment=${5:-} append=${6:-false} | |
[ ! -f "$file" ] && { echo "File not found: $file"; return 1; } | |
local formatted_value=$(perl -e 'use strict; use warnings; my ($value, $append) = @ARGV; | |
my @elements = split(/[;,]/, $value); for my $el (@elements) { if ($el =~ /^[.\/~]?[-a-zA-Z0-9_\/\\]+(\.[a-zA-Z0-9]+)?$/) { | |
$el =~ s/ /\\ /g; } elsif ($el =~ /^(true|false)$/i) { $el = lc $el; } elsif ($el =~ /^[+-]?[0-9]+\.[0-9]+$/) { | |
$el = "\"$el\""; } elsif ($el =~ /^[0-9]+(\.[0-9]+)?[KMGTEP]B$/i) { $el = uc $el; } elsif ($el !~ /^[+-]?[0-9]+$/) { | |
$el = "\"$el\""; } } $value = join(",", @elements); if ($append eq "true") { open my $fh, "<", $ARGV[2] | |
or die "Could not open file: $!"; my $content = do { local $/; <$fh> }; close $fh; if ($content =~ /\['"$section"'\].*^\s*'"$key"'=([^\n]*)/ms) { | |
my $existing_value = $1; $value = $existing_value . "," . $value unless $existing_value =~ /\Q$value\E/; } | |
print $value;' "$raw_value" "$append" "$file") | |
perl -i -pe 'BEGIN {$/ = "";} s/\r\n/\n/g; s/[^\x00-\x7F]//g; s/^\s+|\s+$//g; | |
s/^(#|;).*?\n//mg if $. == 1; s/^\['"$section"'\]\K(.*?)(\n\n|\Z)/$1 =~ s/^\s*'"$key"'=.*\n//rm . "'"$key"'='"$formatted_value"'\n"/es;' "$file" | |
[ -n "$comment" ] && perl -i -pe 's/(?<=\n)^\['"$section"'\]/\n# '"$comment"'\n\['"$section"'\]/' "$file" | |
perl -i -pe 's/(?<!\n\n)\n\[/\n\n\[/g' "$file" | |
} | |
# fetch_ini_file: Retrieves the value of a specific key from a specific section of an INI file | |
# Arguments: | |
# file: The INI file to read | |
# section: The section in the INI file | |
# key: The key whose value is to be retrieved | |
fetch_ini_file() { | |
local file=$1 section=$2 key=$3 | |
[ ! -f "$file" ] && { echo "File not found: $file"; return 1; } | |
local value=$(perl -ne 'my $section_found = 0; if (/^\['"$section"'\]/) { $section_found = 1; } | |
if ($section_found && /^\s*'"$key"'=([^#\n;]+)/) { print "$1\n"; exit; } | |
$section_found = 0 if /^\[/ && !/^\['"$section"'\]/;' "$file") | |
if [[ $value =~ , ]]; then IFS=',' read -r -a array <<< "$value"; echo "${array[@]}"; else echo "$value"; fi | |
} | |
# test_ini_file: Test case for the INI file parselib | |
# Arguments: | |
# file: The INI file to generate | |
test_ini_file() { | |
local file=$1 | |
local max_sections=$((RANDOM % 5 + 1)) | |
local max_keys=$((RANDOM % 5 + 1)) | |
local sections=() | |
for ((section = 1; section <= max_sections; section++)); do | |
local section_name="section$section" | |
sections+=("$section_name") | |
for ((key = 1; key <= max_keys; key++)); do | |
local key_name="key$key" | |
local update_or_add=$((RANDOM % 2)) | |
local value_type=$((RANDOM % 7)) | |
case $value_type in | |
0) | |
local value="\"String$(date +%N)\"" | |
;; | |
1) | |
local value=$((RANDOM % 100)) | |
;; | |
2) | |
local value="$(echo "scale=2; $RANDOM/100" | bc)" | |
;; | |
3) | |
local value="true" | |
;; | |
4) | |
local value="\"Path/to/file$(date +%N).txt\"" | |
;; | |
5) | |
local array_size=$((RANDOM % 4 + 2)) | |
local value="" | |
for ((i = 0; i < array_size; i++)); do | |
local array_element_type=$((RANDOM % 6)) | |
local array_element | |
case $array_element_type in | |
0) | |
array_element="\"String$(date +%N)\"" | |
;; | |
1) | |
array_element=$((RANDOM % 100)) | |
;; | |
2) | |
array_element="$(echo "scale=2; $RANDOM/100" | bc)" | |
;; | |
3) | |
array_element=$([ $((RANDOM % 2)) == 1 ] && echo "true" || echo "false") | |
;; | |
4) | |
array_element="\"Path$(date +%N).txt\"" | |
;; | |
5) | |
array_element="${RANDOM}$(echo "KB MB GB TB" | tr ' ' '\n' | shuf -n 1)" | |
;; | |
*) | |
array_element="\"String$(date +%N)\"" | |
;; | |
esac | |
value+="$array_element" | |
if ((i < array_size - 1)); then | |
value+="," | |
fi | |
done | |
;; | |
6) | |
local value="${RANDOM}$(echo "KB MB GB TB" | tr ' ' '\n' | shuf -n 1)" | |
;; | |
esac | |
if [[ $update_or_add -eq 0 && ${#sections[@]} -gt 0 ]]; then | |
local random_section="${sections[$RANDOM % ${#sections[@]}]}" | |
update_ini_file "$file" "$random_section" "$key_name" "$value" | |
else | |
update_ini_file "$file" "$section_name" "$key_name" "$value" | |
fi | |
local fetched_value=$(fetch_ini_file "$file" "$section_name" "$key_name") | |
echo "Fetched Value: $fetched_value" | |
done | |
done | |
} | |
test_ini_file "test.ini" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment