Initial commit.

This commit is contained in:
Darren 'Tadgy' Austin 2019-07-16 12:41:49 +01:00
commit 2dda2e227d
52 changed files with 2704 additions and 0 deletions

42
bits/comments.ini Normal file
View file

@ -0,0 +1,42 @@
# comment 1
; comment 2
# comment 3
; comment 4
# comment 5
; comment 6
# comment 7
; comment 8
# comment 9
; comment 10
# comment 11
; comment 12
# comment 13
; comment 14
#comment 15
;comment 16
##### comment 17
;;;;;;;; comment 18
########## comment 19
;;;; comment 20
# comment 21
;comment 22
#
# comment 23 #
# # comment 24
# # comment 25
Valid 1
[header1]
Valid 2
Valid 3
Valid 4
[ header 2 ]
Valid 5
[ header 3 ]
[header_____4____]
[ $%"%^ ]

View file

@ -0,0 +1,10 @@
global key 1 = value 1
[ section 1 ]
key 1 = value 1
[ section 2 ]
key 1 = value 1
[ section 1 ]
key 2 = value 2

314
bits/key-blanks.ini Normal file
View file

@ -0,0 +1,314 @@
#######################################################
# Key format tests: = as deliminator #
# Blanks at the start of, in, and after each key name #
#######################################################
# Blanks in keys.
[blanks]
keyformattest1a= No blanks in key name, no blanks before or after key name
key formattest1b= Single space in key name, no blanks before or after key name
key format test 1c= Multiple spaces in key name, no blanks before or after key name
key format test 1d= Multiple consecutive spaces in key name, no blanks before or after key name
key formattest1e= Single tab in key name, no blanks before or after key name
key format test 1f= Multiple tabs in key name, no blanks before or after key name
key format test 1g= Multiple consecutive tabs in key name, no blanks before or after key name
# Blanks before keys.
[single space before key name]
keyformattest2a= No blanks in key name
key formattest2b= Single space in key name
key format test 2c= Multiple spaces in key name
key format test 2d= Multiple consecutive spaces in key name
key formattest2e= Single tab in key name
key format test 2f= Multiple tabs in key name
key format test 2g= Multiple consecutive tabs in key name
[multiple spaces before key name]
keyformattest3a= No blanks in key name
key formattest3b= Single space in key name
key format test 3c= Multiple spaces in key name
key format test 3d= Multiple consecutive spaces in key name
key formattest3e= Single tab in key name
key format test 3f= Multiple tabs in key name
key format test 3g= Multiple consecutive tabs in key name
[single tab before key name]
keyformattest4a= No blanks in key name
key formattest4b= Single space in key name
key format test 4c= Multiple spaces in key name
key format test 4d= Multiple consecutive spaces in key name
key formattest4e= Single tab in key name
key format test 4f= Multiple tabs in key name
key format test 4g= Multiple consecutive tabs in key name
[multiple tabs before key name]
keyformattest5a= No blanks in key name
key formattest5b= Single space in key name
key format test 5c= Multiple spaces in key name
key format test 5d= Multiple consecutive spaces in key name
key formattest5e= Single tab in key name
key format test 5f= Multiple tabs in key name
key format test 5g= Multiple consecutive tabs in key name
[single space after key name]
keyformattest6a = No blanks in key name
key formattest6b = Single space in key name
key format test 6c = Multiple spaces in key name
key format test 6d = Multiple consecutive spaces in key name
key formattest6e = Single tab in key name
key format test 6f = Multiple tabs in key name
key format test 6g = Multiple consecutive tabs in key name
[multiple spaces after key name]
keyformattest7a = No blanks in key name
key formattest7b = Single space in key name
key format test 7c = Multiple spaces in key name
key format test 7d = Multiple consecutive spaces in key name
key formattest7e = Single tab in key name
key format test 7f = Multiple tabs in key name
key format test 7g = Multiple consecutive tabs in key name
[single tab after key name]
keyformattest8a = No blanks in key name
key formattest8b = Single space in key name
key format test 8c = Multiple spaces in key name
key format test 8d = Multiple consecutive spaces in key name
key formattest8e = Single tab in key name
key format test 8f = Multiple tabs in key name
key format test 8g = Multiple consecutive tabs in key name
[multiple tabs after key name]
keyformattest9a = No blanks in key name
key formattest9b = Single space in key name
key format test 9c= Multiple spaces in key name
key format test 9d = Multiple consecutive spaces in key name
key formattest9e = Single tab in key name
key format test 9f = Multiple tabs in key name
key format test 9g = Multiple consecutive tabs in key name
[single space before and single space after key name]
keyformattest10a = No blanks in key name
key formattest10b = Single space in key name
key format test 10c = Multiple spaces in key name
key format test 10d = Multiple consecutive spaces in key name
key formattest10e = Single tab in key name
key format test 10f = Multiple tabs in key name
key format test 10g = Multiple consecutive tabs in key name
[multiple spaces before and single space after key name]
keyformattest11a = No blanks in key name
key formattest11b = Single space in key name
key format test 11c = Multiple spaces in key name
key format test 11d = Multiple consecutive spaces in key name
key formattest11e = Single tab in key name
key format test 11f = Multiple tabs in key name
key format test 11g = Multiple consecutive tabs in key name
[single tab before and single space after key name]
keyformattest12a = No blanks in key name
key formattest12b = Single space in key name
key format test 12c = Multiple spaces in key name
key format test 12d = Multiple consecutive spaces in key name
key formattest12e = Single tab in key name
key format test 12f = Multiple tabs in key name
key format test 12g = Multiple consecutive tabs in key name
[multiple tabs before and single space after key name]
keyformattest13a = No blanks in key name
key formattest13b = Single space in key name
key format test 13c = Multiple spaces in key name
key format test 13d = Multiple consecutive spaces in key name
key formattest13e = Single tab in key name
key format test 13f = Multiple tabs in key name
key format test 13g = Multiple consecutive tabs in key name
[single space before and multiple spaces after key name]
keyformattest14a = No blanks in key name
key formattest14b = Single space in key name
key format test 14c = Multiple spaces in key name
key format test 14d = Multiple consecutive spaces in key name
key formattest14e = Single tab in key name
key format test 14f = Multiple tabs in key name
key format test 14g = Multiple consecutive tabs in key name
[multiple spaces before and multiple spaces after key name]
keyformattest15a = No blanks in key name
key formattest15b = Single space in key name
key format test 15c = Multiple spaces in key name
key format test 15d = Multiple consecutive spaces in key name
key formattest15e = Single tab in key name
key format test 15f = Multiple tabs in key name
key format test 15g = Multiple consecutive tabs in key name
[single tab before and multiple spaces after key name]
keyformattest16a = No blanks in key name
key formattest16b = Single space in key name
key format test 16c = Multiple spaces in key name
key format test 16d = Multiple consecutive spaces in key name
key formattest16e = Single tab in key name
key format test 16f = Multiple tabs in key name
key format test 16g = Multiple consecutive tabs in key name
[multiple tabs before and multiple spaces after key name]
keyformattest17a = No blanks in key name
key formattest17b = Single space in key name
key format test 17c = Multiple spaces in key name
key format test 17d = Multiple consecutive spaces in key name
key formattest17e = Single tab in key name
key format test 17f = Multiple tabs in key name
key format test 17g = Multiple consecutive tabs in key name
[single space before and single tab after key name]
keyformattest18a = No blanks in key name
key formattest18b = Single space in key name
key format test 18c = Multiple spaces in key name
key format test 18d = Multiple consecutive spaces in key name
key formattest18e = Single tab in key name
key format test 18f = Multiple tabs in key name
key format test 18g = Multiple consecutive tabs in key name
[multiple spaces before and single tab after key name]
keyformattest19a = No blanks in key name
key formattest19b = Single space in key name
key format test 19c = Multiple spaces in key name
key format test 19d = Multiple consecutive spaces in key name
key formattest19e = Single tab in key name
key format test 19f = Multiple tabs in key name
key format test 19g = Multiple consecutive tabs in key name
[single tab before and single tab after key name]
keyformattest20a = No blanks in key name
key formattest20b = Single space in key name
key format test 20c = Multiple spaces in key name
key format test 20d = Multiple consecutive spaces in key name
key formattest20e = Single tab in key name
key format test 20f = Multiple tabs in key name
key format test 20g = Multiple consecutive tabs in key name
[multiple tabs before and single tab after key name]
keyformattest21a = No blanks in key name
key formattest21b = Single space in key name
key format test 21c = Multiple spaces in key name
key format test 21d = Multiple consecutive spaces in key name
key formattest21e = Single tab in key name
key format test 21f = Multiple tabs in key name
key format test 21g = Multiple consecutive tabs in key name
[single space before and multiple tabs after key name]
keyformattest22a = No blanks in key name
key formattest22b = Single space in key name
key format test 22c = Multiple spaces in key name
key format test 22d = Multiple consecutive spaces in key name
key formattest22e = Single tab in key name
key format test 22f = Multiple tabs in key name
key format test 22g = Multiple consecutive tabs in key name
[multiple spaces before and multiple tabs after key name]
keyformattest23a = No blanks in key name
key formattest23b = Single space in key name
key format test 23c = Multiple spaces in key name
key format test 23d = Multiple consecutive spaces in key name
key formattest23e = Single tab in key name
key format test 23f = Multiple tabs in key name
key format test 23g = Multiple consecutive tabs in key name
[single tab before and miltiple tabs after key name]
keyformattest24a = No blanks in key name
key formattest24b = Single space in key name
key format test 24c = Multiple spaces in key name
key format test 24d = Multiple consecutive spaces in key name
key formattest24e = Single tab in key name
key format test 24f = Multiple tabs in key name
key format test 24g = Multiple consecutive tabs in key name
[multiple tabs before and multiple tabs after key name]
keyformattest25a = No blanks in key name
key formattest25b = Single space in key name
key format test 25c = Multiple spaces in key name
key format test 25d = Multiple consecutive spaces in key name
key formattest25e = Single tab in key name
key format test 25f = Multiple tabs in key name
key format test 25g = Multiple consecutive tabs in key name
[random mixture blanks before and single space after key name]
keyformattest26a = No blanks in key name
key formattest26b = Single space in key name
key format test 26c = Multiple spaces in key name
key format test 26d = Multiple consecutive spaces in key name
key formattest26e = Single tab in key name
key format test 26f = Multiple tabs in key name
key format test 26g = Multiple consecutive tabs in key name
[random mixture blanks before and multiple spaces after key name]
keyformattest27a = No blanks in key name
key formattest27b = Single space in key name
key format test 27c = Multiple spaces in key name
key format test 27d = Multiple consecutive spaces in key name
key formattest27e = Single tab in key name
key format test 27f = Multiple tabs in key name
key format test 27g = Multiple consecutive tabs in key name
[random mixture blanks before and single tab after key name]
keyformattest28a = No blanks in key name
key formattest28b = Single space in key name
key format test 28c = Multiple spaces in key name
key format test 28d = Multiple consecutive spaces in key name
key formattest28e = Single tab in key name
key format test 28f = Multiple tabs in key name
key format test 28g = Multiple consecutive tabs in key name
[random mixture blanks before and multiple tabs after key name]
keyformattest29a = No blanks in key name
key formattest29b = Single space in key name
key format test 29c = Multiple spaces in key name
key format test 29d = Multiple consecutive spaces in key name
key formattest29e = Single tab in key name
key format test 29f = Multiple tabs in key name
key format test 29g = Multiple consecutive tabs in key name
[single space before and random mixture blanks after key name]
keyformattest30a = No blanks in key name
key formattest30b = Single space in key name
key format test 30c = Multiple spaces in key name
key format test 30d = Multiple consecutive spaces in key name
key formattest30e = Single tab in key name
key format test 30f = Multiple tabs in key name
key format test 30g = Multiple consecutive tabs in key name
[multiple spaces before and random mixture blanks after key name]
keyformattest31a = No blanks in key name
key formattest31b = Single space in key name
key format test 31c = Multiple spaces in key name
key format test 31d = Multiple consecutive spaces in key name
key formattest31e = Single tab in key name
key format test 31f = Multiple tabs in key name
key format test 31g = Multiple consecutive tabs in key name
[single tab before and random mixture blanks after key name]
keyformattest32a = No blanks in key name
key formattest32b = Single space in key name
key format test 32c = Multiple spaces in key name
key format test 32d = Multiple consecutive spaces in key name
key formattest32e = Single tab in key name
key format test 32f = Multiple tabs in key name
key format test 32g = Multiple consecutive tabs in key name
[multiple tabs before and random mixture blanks after key name]
keyformattest33a = No blanks in key name
key formattest33b = Single space in key name
key format test 33c = Multiple spaces in key name
key format test 33d = Multiple consecutive spaces in key name
key formattest33e = Single tab in key name
key format test 33f = Multiple tabs in key name
key format test 33g = Multiple consecutive tabs in key name
[random mixture blanks before and after key name]
keyformattest34a = No blanks in key name
key formattest34b = Single space in key name
key format test 34c = Multiple spaces in key name
key format test 34d = Multiple consecutive spaces in key name
key formattest34e = Single tab in key name
key format test 34f = Multiple tabs in key name
key format test 34g = Multiple consecutive tabs in key name

View file

@ -0,0 +1,234 @@
#!@BASH_PATH@
# Author: Jack L. Frost <fbt@fleshless.org>
# Licensed under the Internet Software Consortium (ISC) license.
# See LICENSE for its text.
_self="${0##*/}"
err() { printf '%s\n' "$*" >&2; }
debug() {
(( $flag_debug )) && { printf '%s\n' "DEBUG: $*"; }
}
usage() {
while read; do printf '%s\n' "$REPLY"; done <<- EOF
Usage: $_self [flags]
Flags:
-h|--help Show this message.
-c|--config <file> Use a config specified by <file>.
-d|--debug Enable debug messages.
EOF
}
cfg_load() {
declare section line key value
declare -g -A cfg
mapfile -t config < "$1"
for line in "${config[@]}"; do
if [[ "$line" =~ ^\[.+\] ]]; then
section="${line//[\[\]]/}"
case "$section" in
main) :;;
*) ifaces+=( "${line//[\[\]]/}" );;
esac
elif [[ "$line" =~ ^('#'|\s+?$) ]]; then
:
else
IFS='=' read -r key value <<< "$line"
if ! [[ "$section" ]]; then
err "Key $key does not belong to a section!"
return 1
fi
if [[ "$key" ]]; then
if ! [[ "$value" ]]; then
value=1
fi
if [[ ${cfg[${section}_$key]} ]]; then
declare -g cfg["${section}_$key"]="${cfg[${section}_$key]}#${value}"
else
declare -g cfg["${section}_$key"]="$value"
fi
fi
fi
done
}
net_up() {
for iface in "${ifaces[@]}"; do
# Prepare the interface
if [[ "${cfg[${iface}_preup]}" ]]; then
${cfg[${iface}_preup]}
fi
# Bring the interface up
if [[ "${cfg[${iface}_up]}" ]]; then
${cfg[${iface}_up]}
else
if [[ "${cfg[${iface}_vlan_dev]}" ]]; then
ip link add link "${cfg[${iface}_vlan_dev]}" name "$iface" type vlan id "${cfg[${iface}_vlan_id]}"
fi
ip link set "$iface" up
fi
# Add IPs
if [[ "${cfg[${iface}_ip]}" ]]; then
IFS='#' read -r -a ips <<< "${cfg[${iface}_ip]}"
for a in "${ips[@]}"; do
ip addr add "$a" dev "$iface"
done
fi
# Configure the interface with dhcp if needed
if [[ "${cfg[${iface}_dhcp]}" ]]; then
${cfg[main_dhcp_up]} "$iface"
fi
# Add routes
if [[ "${cfg[${iface}_route]}" ]]; then
IFS='#' read -r -a routes <<< "${cfg[${iface}_route]}"
for r in "${routes[@]}"; do
read -r net gw <<< "$r"
ip route add "$net" via "$gw"
done
fi
if [[ "${cfg[${iface}_postup]}" ]]; then
${cfg[${iface}_up]}
fi
done
}
net_down() {
for iface in "${ifaces[@]}"; do
# Prepare the interface
if [[ "${cfg[${iface}_predown]}" ]]; then
${cfg[${iface}_predown]}
fi
# Remove routes
if [[ "${cfg[${iface}_route]}" ]]; then
IFS='#' read -r -a routes <<< "${cfg[${iface}_route]}"
for r in "${routes[@]}"; do
read -r net gw <<< "$r"
ip route del "$net" via "$gw"
done
fi
# Stop dhcpcd
if [[ "${cfg[${iface}_dhcp]}" ]]; then
${cfg[main_dhcp_down]} "$iface"
fi
# Remove IPs
if [[ "${cfg[${iface}_ip]}" ]]; then
IFS='#' read -r -a ips <<< "${cfg[${iface}_ip]}"
for a in "${ips[@]}"; do
ip addr del "$a" dev "$iface"
done
fi
# Bring the interface down
if [[ "${cfg[${iface}_down]}" ]]; then
${cfg[${iface}_down]}
else
ip link set "$iface" down
if [[ "${cfg[${iface}_vlan_dev]}" ]]; then
ip link del "$iface"
fi
fi
if [[ "${cfg[${iface}_postdown]}" ]]; then
${cfg[${iface}_postdown]}
fi
done
}
set_argv() {
declare arg opt c
declare -g argv
while (( $# )); do
unset -v arg opt c
case "$1" in
(--) argv+=( "$1" ); break;;
(--*)
IFS='=' read arg opt <<< "$1"
argv+=( "$arg" )
[[ "$opt" ]] && {
argv+=( "$opt" )
}
;;
(-*)
while read -n1 c
do
case "$c" in
-|'') :;;
*) argv+=( "-$c" );;
esac
done <<< "$1"
;;
(*) argv+=( "$1" );;
esac
shift
done
}
main() {
while (( $# )); do
case "$1" in
-h|--help) usage; return 0;;
-d|--debug)
flag_debug=1
debug "Debug flag set."
;;
-c|--config) cfg_file="$2"; shift;;
--) shift; break;;
-*)
err "Unknown key: $1"
usage
return 1
;;
*) break;;
esac
shift
done
if ! [[ "$cfg_file" ]]; then
cfg_file='@CONFDIR@/networking'
fi
cfg_load "$cfg_file" || {
return "$?"
}
action=${1:-"up"}
case "$action" in
up) net_up;;
down) net_down;;
esac
}
set_argv "$@"
main "${argv[@]}"

3
bits/other-peoples/sites Normal file
View file

@ -0,0 +1,3 @@
https://ajdiaz.wordpress.com/2008/02/09/bash-ini-parser/
https://github.com/rudimeier/bash_ini_parser

View file

@ -0,0 +1,118 @@
bash_ini_parser -- Simple INI file parser
=========================================
This is a comfortable and simple INI file parser to be used in
bash scripts.
COPYRIGHT
---------
Copyright (c) 2009 Kevin Porter / Advanced Web Construction Ltd
(http://coding.tinternet.info / http://webutils.co.uk)
Copyright (c) 2010, 2011 Ruediger Meier <sweet_f_a@gmx.de>
(https://github.com/rudimeier/)
USAGE
-----
You must source the bash file into your script:
> . read_ini.sh
and then use the read_ini function, defined as:
> read_ini INI_FILE [SECTION] [[--prefix|-p] PREFIX] [[--booleans|b] [0|1]]
If SECTION is supplied, then only the specified section of the file will
be processed.
After running the read_ini function, variables corresponding to the ini
file entries will be available to you. Naming convention for variable
names is:
PREFIX__SECTION__VARNAME
PREFIX is 'INI' by default (but can be changed with the --prefix option),
SECTION and VARNAME are the section name and variable name respectively.
For example, to read and output the variables of this ini file:
-- START test1.ini file
var1="VAR 1"
var2 = VAR 2
[section1]
var1="section1 VAR 1"
var2= section1 VAR 2
-- END test1.ini file
you could do this:
-- START bash script
. read_ini.sh
read_ini test1.ini
echo "var1 = ${INI__var1}"
echo "var2 = ${INI__var2}"
echo "section1 var1 = ${INI__section1__var1}"
echo "section1 var2 = ${INI__section1__var2}"
-- END bash script
OPTIONS
-------
[--prefix | -p] PREFIX
String to prepend to generated variable names (automatically followed by '__').
Default: INI
[--booleans | -b] [0|1]
Whether to interpret special unquoted string values 'yes', 'no', 'true',
'false', 'on', 'off' as booleans.
Default: 1
INI FILE FORMAT
---------------
- Variables are stored as name/value pairs, eg:
var=value
- Leading and trailing whitespace of the name and the value is discarded.
- Use double or single quotes to get whitespace in the values
- Section names in square brackets, eg:
[section1]
var1 = value
- Variable names can be re-used between sections (or out of section), eg:
var1=value
[section1]
var1=value
[section3]
var1=value
- Dots are converted to underscores in all variable names.
- Special boolean values: unquoted strings 'yes', 'true' and 'on' are interpreted
as 1; 'no', 'false' and 'off' are interpreted as 0

View file

@ -0,0 +1,7 @@
- Tabs/newlines to be preserved
- [] notation for arrays (like PHP's parse_ini_file())

View file

@ -0,0 +1,272 @@
#
# Copyright (c) 2009 Kevin Porter / Advanced Web Construction Ltd
# (http://coding.tinternet.info, http://webutils.co.uk)
# Copyright (c) 2010, 2011 Ruediger Meier <sweet_f_a@gmx.de>
# (https://github.com/rudimeier/)
#
# Simple INI file parser.
#
# See README for usage.
#
#
function read_ini()
{
# Be strict with the prefix, since it's going to be run through eval
function check_prefix()
{
if ! [[ "${VARNAME_PREFIX}" =~ ^[a-zA-Z_][a-zA-Z0-9_]*$ ]] ;then
echo "read_ini: invalid prefix '${VARNAME_PREFIX}'" >&2
return 1
fi
}
function check_ini_file()
{
if [ ! -r "$INI_FILE" ] ;then
echo "read_ini: '${INI_FILE}' doesn't exist or not" \
"readable" >&2
return 1
fi
}
# enable some optional shell behavior (shopt)
function pollute_bash()
{
if ! shopt -q extglob ;then
SWITCH_SHOPT="${SWITCH_SHOPT} extglob"
fi
if ! shopt -q nocasematch ;then
SWITCH_SHOPT="${SWITCH_SHOPT} nocasematch"
fi
shopt -q -s ${SWITCH_SHOPT}
}
# unset all local functions and restore shopt settings before returning
# from read_ini()
function cleanup_bash()
{
shopt -q -u ${SWITCH_SHOPT}
unset -f check_prefix check_ini_file pollute_bash cleanup_bash
}
local INI_FILE=""
local INI_SECTION=""
# {{{ START Deal with command line args
# Set defaults
local BOOLEANS=1
local VARNAME_PREFIX=INI
local CLEAN_ENV=0
# {{{ START Options
# Available options:
# --boolean Whether to recognise special boolean values: ie for 'yes', 'true'
# and 'on' return 1; for 'no', 'false' and 'off' return 0. Quoted
# values will be left as strings
# Default: on
#
# --prefix=STRING String to begin all returned variables with (followed by '__').
# Default: INI
#
# First non-option arg is filename, second is section name
while [ $# -gt 0 ]
do
case $1 in
--clean | -c )
CLEAN_ENV=1
;;
--booleans | -b )
shift
BOOLEANS=$1
;;
--prefix | -p )
shift
VARNAME_PREFIX=$1
;;
* )
if [ -z "$INI_FILE" ]
then
INI_FILE=$1
else
if [ -z "$INI_SECTION" ]
then
INI_SECTION=$1
fi
fi
;;
esac
shift
done
if [ -z "$INI_FILE" ] && [ "${CLEAN_ENV}" = 0 ] ;then
echo -e "Usage: read_ini [-c] [-b 0| -b 1]] [-p PREFIX] FILE"\
"[SECTION]\n or read_ini -c [-p PREFIX]" >&2
cleanup_bash
return 1
fi
if ! check_prefix ;then
cleanup_bash
return 1
fi
local INI_ALL_VARNAME="${VARNAME_PREFIX}__ALL_VARS"
if [ "${CLEAN_ENV}" = 1 ] ;then
eval unset "\$${INI_ALL_VARNAME}"
fi
unset ${INI_ALL_VARNAME}
if [ -z "$INI_FILE" ] ;then
cleanup_bash
return 0
fi
if ! check_ini_file ;then
cleanup_bash
return 1
fi
# Sanitise BOOLEANS - interpret "0" as 0, anything else as 1
if [ "$BOOLEANS" != "0" ]
then
BOOLEANS=1
fi
# }}} END Options
# }}} END Deal with command line args
local LINE_NUM=0
local SECTION=""
# IFS is used in "read" and we want to switch it within the loop
local IFS=$' \t\n'
local IFS_OLD="${IFS}"
# we need some optional shell behavior (shopt) but want to restore
# current settings before returning
local SWITCH_SHOPT=""
pollute_bash
while read -r line
do
#echo line = "$line"
((LINE_NUM++))
# Skip blank lines and comments
if [ -z "$line" -o "${line:0:1}" = ";" -o "${line:0:1}" = "#" ]
then
continue
fi
# Section marker?
if [[ "${line}" =~ ^\[[a-zA-Z0-9_]{1,}\]$ ]]
then
# Set SECTION var to name of section (strip [ and ] from section marker)
SECTION="${line#[}"
SECTION="${SECTION%]}"
continue
fi
# Are we getting only a specific section? And are we currently in it?
if [ ! -z "$INI_SECTION" ]
then
if [ "$SECTION" != "$INI_SECTION" ]
then
continue
fi
fi
# Valid var/value line? (check for variable name and then '=')
if ! [[ "${line}" =~ ^[a-zA-Z0-9._]{1,}[[:space:]]*= ]]
then
echo "Error: Invalid line:" >&2
echo " ${LINE_NUM}: $line" >&2
cleanup_bash
return 1
fi
# split line at "=" sign
IFS="="
read -r VAR VAL <<< "${line}"
IFS="${IFS_OLD}"
# delete spaces around the equal sign (using extglob)
VAR="${VAR%%+([[:space:]])}"
VAL="${VAL##+([[:space:]])}"
VAR=$(echo $VAR)
# Construct variable name:
# ${VARNAME_PREFIX}__$SECTION__$VAR
# Or if not in a section:
# ${VARNAME_PREFIX}__$VAR
# In both cases, full stops ('.') are replaced with underscores ('_')
if [ -z "$SECTION" ]
then
VARNAME=${VARNAME_PREFIX}__${VAR//./_}
else
VARNAME=${VARNAME_PREFIX}__${SECTION}__${VAR//./_}
fi
eval "${INI_ALL_VARNAME}=\"\$${INI_ALL_VARNAME} ${VARNAME}\""
if [[ "${VAL}" =~ ^\".*\"$ ]]
then
# remove existing double quotes
VAL="${VAL##\"}"
VAL="${VAL%%\"}"
elif [[ "${VAL}" =~ ^\'.*\'$ ]]
then
# remove existing single quotes
VAL="${VAL##\'}"
VAL="${VAL%%\'}"
elif [ "$BOOLEANS" = 1 ]
then
# Value is not enclosed in quotes
# Booleans processing is switched on, check for special boolean
# values and convert
# here we compare case insensitive because
# "shopt nocasematch"
case "$VAL" in
yes | true | on )
VAL=1
;;
no | false | off )
VAL=0
;;
esac
fi
# enclose the value in single quotes and escape any
# single quotes and backslashes that may be in the value
VAL="${VAL//\\/\\\\}"
VAL="\$'${VAL//\'/\'}'"
eval "$VARNAME=$VAL"
done <"${INI_FILE}"
cleanup_bash
}

View file

@ -0,0 +1,28 @@
DIR=$(dirname $0)
cd $DIR
TESTS=$(ls test*.sh | grep -v test.sh | sed 's/\.sh$//')
for test in $TESTS
do
bash $test.sh &> $test.out
# bash $test.sh >$test.out 2>$test.err
# Fail and bail out if test didn't pass
PASSED=$(diff $test.out $test.out.correct 2>&1)
if [ ! -z "$PASSED" ]
then
echo "Test $test failed. Output is in $DIR/$test.out"
exit 1
else
rm -rf $test.out
fi
done
echo "All tests passed"

View file

@ -0,0 +1,40 @@
; Comment beginning with ';'
# Comment beginning with '#'
; var1 - simple var
var1=VAR 1
; var2 - space before '='; leading space that should be stripped
var2 = VAR 2
; var3 - with leading and trailing space that should be stripped
var3 = VAR 3
; var4 - value in double quotes
var4="VAR 4"
; var5 - value in double quotes; value's leading and trailing whitespace should
; be preserved; leading and trailing whitespace before/after double quotes should
; not become part of the value
var5 = " VAR 5 "
; var6 - value in double quotes; value's leading and trailing whitespace should
; be preserved; leading and trailing whitespace before/after double quotes should
; not become part of the value
var6 = ' VAR 6 '
; var7 - value contains a single double quote
var7 = VAR " 7
; var8 - value contains a single single quote
var8 = VAR ' 8
; var9 - leading whitespace before variable name
var9=VAR 9
; var10 - leading whitespace before variable name
var10 = VAR 10

View file

@ -0,0 +1,10 @@
var1:VAR 1
var2:VAR 2
var3:VAR 3
var4:VAR 4
var5: VAR 5
var6: VAR 6
var7:VAR " 7
var8:VAR ' 8
var9:VAR 9
var10:VAR 10

View file

@ -0,0 +1,21 @@
# Test 1
#
# Basic variable values; leading/trailing whitespace; comments
. ../read_ini.sh
read_ini test1.ini
#echo "a:LOCALVAR=$LOCALVAR"
echo "var1:$INI__var1"
echo "var2:$INI__var2"
echo "var3:$INI__var3"
echo "var4:$INI__var4"
echo "var5:$INI__var5"
echo "var6:$INI__var6"
echo "var7:$INI__var7"
echo "var8:$INI__var8"
echo "var9:$INI__var9"
echo "var10:$INI__var10"

View file

@ -0,0 +1,8 @@
var1=VAR1
; Invalid line - should throw an error and stop processing
INVALID LINE
var2=VAR2

View file

@ -0,0 +1,2 @@
Error: Invalid line:
6: INVALID LINE

View file

@ -0,0 +1,8 @@
# Test 2
#
# Invalid line
. ../read_ini.sh
read_ini test2.ini

View file

@ -0,0 +1,23 @@
; Testing sections
var1=VAR 1
var2= "VAR 2 "
[section1]
var1="section 1 VAR 1"
var2= "section 1 VAR 2"
var3 = "section 1 VAR 3 "
[section2]
var1 = section 2 VAR 1
var2=" section 2 VAR 2"
var3=section 2 VAR 3
var4=section 2 VAR 4
var5=section 2 VAR 5
[section3]
var1="section 3 VAR 1"
var2= "section 3 VAR 2"

View file

@ -0,0 +1,12 @@
var1:VAR 1
var2:VAR 2
setion1_var1:section 1 VAR 1
setion1_var2:section 1 VAR 2
setion1_var3:section 1 VAR 3
setion2_var1:section 2 VAR 1
setion2_var2: section 2 VAR 2
setion2_var3:section 2 VAR 3
setion2_var4:section 2 VAR 4
setion2_var5:section 2 VAR 5
setion3_var1:section 3 VAR 1
setion3_var2:section 3 VAR 2

View file

@ -0,0 +1,25 @@
# Test 3
#
# Sections
. ../read_ini.sh
read_ini test3.ini
echo "var1:$INI__var1"
echo "var2:$INI__var2"
echo "setion1_var1:$INI__section1__var1"
echo "setion1_var2:$INI__section1__var2"
echo "setion1_var3:$INI__section1__var3"
echo "setion2_var1:$INI__section2__var1"
echo "setion2_var2:$INI__section2__var2"
echo "setion2_var3:$INI__section2__var3"
echo "setion2_var4:$INI__section2__var4"
echo "setion2_var5:$INI__section2__var5"
echo "setion3_var1:$INI__section3__var1"
echo "setion3_var2:$INI__section3__var2"

View file

@ -0,0 +1,14 @@
; Testing dots in variable names (these get converted to underscores in
; output variable names)
var.1 = "VAR 1"
var.two="VAR 2"
var.3.two_dots="VAR 3"
[section1]
var.1="section 1 VAR 1"
var.two="section 1 VAR 2"

View file

@ -0,0 +1,5 @@
var_1:VAR 1
var_two:VAR 2
var_3_two_dots:VAR 3
section 1 var_1:section 1 VAR 1
section 1 var_two:section 1 VAR 2

View file

@ -0,0 +1,15 @@
# Test 4
#
# Dots in variable names (converted to underscores in output var names)
. ../read_ini.sh
read_ini test4.ini
echo "var_1:$INI__var_1"
echo "var_two:$INI__var_two"
echo "var_3_two_dots:$INI__var_3_two_dots"
echo "section 1 var_1:$INI__section1__var_1"
echo "section 1 var_two:$INI__section1__var_two"

View file

@ -0,0 +1,13 @@
; Testing prevention of in-value code execution via eval
var1 = blah blah `ls` blah
var2 = blah blah $(ls) blah
; these code injections worked on 0.3
var3 = blah blah \\`ls\\` blah
var4 = blah blah \\$(ls) blah
; these code injections could work with read -r
var5 = blah blah \`ls\` blah
var6 = blah blah \$(ls) blah

View file

@ -0,0 +1,6 @@
var1:blah blah `ls` blah
var2:blah blah $(ls) blah
var3:blah blah \\`ls\\` blah
var4:blah blah \\$(ls) blah
var5:blah blah \`ls\` blah
var6:blah blah \$(ls) blah

View file

@ -0,0 +1,16 @@
# Test 5
#
# Prevention of in-value code execution via backticks or $() notation.
# This must be done because the value is run through an eval statement.
. ../read_ini.sh
read_ini test5.ini
echo "var1:$INI__var1"
echo "var2:$INI__var2"
echo "var3:$INI__var3"
echo "var4:$INI__var4"
echo "var5:$INI__var5"
echo "var6:$INI__var6"

View file

@ -0,0 +1,27 @@
; Testing processing of special boolean constants: unquoted
; strings 'yes', 'true' and 'on' are interpreted as 1;
; unquoted strings 'no', 'false' and 'off' as 0.
yes1 = yes
yes2 = "yes"
yes3 = Yes
true1=true
true2= true
true3 = "tRuE"
on1 = on
on2 = oN
on3 = "ON"
no1 = no
no2 = "no"
no3=No
false1 = false
false2 = faLSe
false3 = "FALSE"
off1 = off
off2 = Off
off3 = "off"

View file

@ -0,0 +1,30 @@
yes1:1
yes2:yes
yes3:1
true1:1
true2:1
true3:tRuE
on1:1
on2:1
on3:ON
no1:0
no2:no
no3:0
false1:0
false2:0
false3:FALSE
off1:0
off2:0
off3:off
yes1:1
true2:1
on3:ON
no3:0
false2:0
off1:0
yes1:yes
true2:true
on3:ON
no3:No
false2:faLSe
off1:off

View file

@ -0,0 +1,56 @@
# Testing booleans processing
# First: with default booleans processing (on)
. ../read_ini.sh
read_ini test6.ini
echo "yes1:$INI__yes1"
echo "yes2:$INI__yes2"
echo "yes3:$INI__yes3"
echo "true1:$INI__true1"
echo "true2:$INI__true2"
echo "true3:$INI__true3"
echo "on1:$INI__on1"
echo "on2:$INI__on2"
echo "on3:$INI__on3"
echo "no1:$INI__no1"
echo "no2:$INI__no2"
echo "no3:$INI__no3"
echo "false1:$INI__false1"
echo "false2:$INI__false2"
echo "false3:$INI__false3"
echo "off1:$INI__off1"
echo "off2:$INI__off2"
echo "off3:$INI__off3"
# Second: with booleans processing explicitly turned on via "--booleans 1"
. ../read_ini.sh
read_ini --booleans 1 test6.ini
echo "yes1:$INI__yes1"
echo "true2:$INI__true2"
echo "on3:$INI__on3"
echo "no3:$INI__no3"
echo "false2:$INI__false2"
echo "off1:$INI__off1"
# Third: with booleans processing explicity switched off via "--booleans 0"
. ../read_ini.sh
read_ini test6.ini --booleans 0
echo "yes1:$INI__yes1"
echo "true2:$INI__true2"
echo "on3:$INI__on3"
echo "no3:$INI__no3"
echo "false2:$INI__false2"
echo "off1:$INI__off1"

View file

@ -0,0 +1,8 @@
; Simple definitions for testing --prefix option
var1=VAR 1
[section1]
var1 = "section 1 VAR 1"

View file

@ -0,0 +1,7 @@
# 1
var1:VAR 1
section1 var1:section 1 VAR 1
# 2
read_ini: invalid prefix 'PR:EFIX,'
# 3
read_ini: invalid prefix '1PREFIX'

View file

@ -0,0 +1,30 @@
# Test 7
#
# Option: [--prefix | -p] PREFIX
# First: valid value for prefix
echo "# 1"
. ../read_ini.sh
read_ini test7.ini --prefix PREFIX1
echo "var1:$PREFIX1__var1"
echo "section1 var1:$PREFIX1__section1__var1"
# Second: invalid value for prefix (contains illegal chars)
echo "# 2"
. ../read_ini.sh
read_ini -p PR:EFIX, test7.ini &&
{
echo "var1:$PREFIX1__var1"
echo "section1 var1:$PREFIX1__section1__var1"
}
# Third: invalid value for prefix (begins with a number)
echo "# 3"
. ../read_ini.sh
read_ini --prefix 1PREFIX test7.ini &&
{
echo "var1:$PREFIX1__var1"
echo "section1 var1:$PREFIX1__section1__var1"
}

View file

@ -0,0 +1,4 @@
; this code injection via section worked on 0.3
[x=blah; ls ;]
var1 = blah

View file

@ -0,0 +1,2 @@
Error: Invalid line:
3: [x=blah; ls ;]

View file

@ -0,0 +1,9 @@
# Test 8
#
# Prevention of in-value code execution via invalid section
. ../read_ini.sh
read_ini test8.ini

View file

@ -0,0 +1,12 @@
; Testing quoted quotes (didnt't worked in 0.3)
; code injection
var1="" ls "."
var2='' ls '.'
; or just an error: unexpected EOF while looking for matching `"'
var3="""
var4='''
var5="
var6='

View file

@ -0,0 +1,6 @@
var1:" ls ".
var2:' ls '.
var3:"
var4:'
var5:"
var6:'

View file

@ -0,0 +1,16 @@
# Test 9
#
# further stuff which didn't worked in 0.3
. ../read_ini.sh
if ! read_ini test9.ini ;then exit 1; fi
echo "var1:$INI__var1"
echo "var2:$INI__var2"
echo "var3:$INI__var3"
echo "var4:$INI__var4"
echo "var5:$INI__var5"
echo "var6:$INI__var6"

View file

@ -0,0 +1 @@
https://github.com/rudimeier/bash_ini_parser

34
bits/quotes-sed.sh Normal file
View file

@ -0,0 +1,34 @@
{ echo "keyname1 = line without quotes"
echo "keyname2 = line with 1 \" double quote"
echo "keyname3 = line with \" 2 double \" quotes"
echo "keyname4 = line \\"
echo "with continuation \\"
echo "at end"
echo "keyname5 = \"double quoted text, single line\""
echo "keyname6 = 'single quoted text, single line'"
echo "keyname7 = \"double quoted text"
echo "over 1"
echo "2"
echo "3"
echo "4 \""; } |
sed -re "{
# Insert [ at beginning of key
s/^[[:blank:]]*/['/
# Insert ] at end of key
s/[[:blank:]]*=/']=/
# Branch if there's a =<quote> ...
/^.*[^\\]=[[:blank:]]*['\"]/ {
p
:x
# Branch if there is no <quote> at end of line ...
/.*['\"][[:blank:]]*\$/ ! {
# Read new line
N
# Insert a \n
s/\\\n//
# Continue loop if s/ above was successful
tx
}
}
s/(^|$)/#/g
}"

76
bits/readline/readline Executable file
View file

@ -0,0 +1,76 @@
#!/bin/bash
shopt -s extglob
exec {FD}<readline.ini
#key2value() {
# # SECTION=
# KEY="$1"
#
# if [[ "${VALUE:0:1}" =~ [\"\'] ]]; then
# printf "%s" "${VALUE:1:-1}"
# else
# printf "%s" "$VALUE"
# fi
#}
while :; do
LINE=""
while :; do
# The 'read' will remove leading whitespace from the line.
read -r -u $FD REPLY || break 2
# Handle line continuations.
if [[ "${REPLY: -1:1}" == "\\" ]]; then
LINE+="${REPLY:0:-1}"
continue
else
LINE+="$REPLY"
break
fi
done
# Ignore the line if it's a comment.
# FIXME: Make it so the comments can be # or ; or both.
[[ "$LINE" =~ ^[[:blank:]]*([#\;].*)*$ ]] && continue
# Remove trailing whitespace from key part.
LINE="${LINE/+([[:blank:]])=/=}"
# Remove leading whitespace from value part.
LINE="${LINE/=+([[:blank:]])/=}"
# Extract the key and the value
KEY="${LINE%%=*}"
VALUE="${LINE#*=}"
# If the value starts with a " or ' it must end with same.
if [[ "${VALUE:0:1}" =~ [\"\'] ]]; then
if [[ "${VALUE:0:1}" != "${VALUE: -1:1}" ]]; then
echo "Unmatched quotes - ignoring line."
continue
fi
fi
printf "<%s> = <%s>\n" "$KEY" "$VALUE"
unset FOO
declare -A FOO
FOO["$KEY"]=$VALUE
printf "%s\n" "$(key2value "$KEY")"
# printf "%q\n" "$VALUE"
# declare -p FOO
echo
done
# FOO="test1 = test2 = test3"
# KEY="${FOO%%=*}"
# VALUE="${FOO#*=}"

View file

@ -0,0 +1,18 @@
# test
; test
# test
; test
foo = This is a line with \
a backslash \
# foo
\
#bar = This is a line without a backslash
#baz = " This is a = \
# line in \
#quotes "
foo = 'Test \' $BASH_SOURCE'
bar = "Test 2 ' \""
#foof = This is $BASH_SOURCE line without quotes

View file

@ -0,0 +1,23 @@
#!/bin/bash
INIFILE=sanatise_section.ini
if ! exec 10<"$INIFILE"; then
echo "${0##*/}: $INIFILE: failed to open"
return 1
fi
shopt -s extglob
# Parse the ini file
IFS=$'\n'
BUFFER=""
while :; do
# Read a line of input from the file descriptor
read -u 10 LINE || break
# printf -- "->%s<-\n" "$LINE"
LINE="${LINE/#*([[:blank:]])\[*([[:blank:]])/}"
LINE="${LINE/%*([[:blank:]])\]*([[:blank:]])/}"
printf -- "->%s<-\n" "$LINE"
done

View file

@ -0,0 +1,8 @@
[test 1]
[ test 2]
[ test 3 ]
[ test 4 ]
[ test 5 ]
[ test 6 ]
[ test 7 ]
[test 8]

View file

@ -0,0 +1,185 @@
#!/bin/bash
# Notes:
# Cannot use any of the deliminators in the key name
# Todo:
# Lines beginning with #; within " .. " blocks on new lines will be stripped.
# Allow merging of multiple sections with the same name
# Change case of variables: \L \U \E
# export SECLIST="SECTIONS"
# Allow delims to be specified in a var - don't assume =:
export VARPREFIX="INI_"
export SECPREFIX="SECTION_"
export SECCNAMEKEY="%cannonical name%"
export TOPSEC="global"
initest() {
echo "declare -A ${VARPREFIX}${SECPREFIX}${TOPSEC}=("
echo "[${SECCNAMEKEY}]=\"${TOPSEC}\""
cat $1 | sed -r "{
# Ignore blank lines and comments
/^[[:blank:]]*(#|;|$)/ d
# Handle [section] lines
/^[[:blank:]]*\[.*\][[:blank:]]*$/ {
i )
s/(^[[:blank:]]*\[[[:blank:]]*|[[:blank:]]*\][[:blank:]]*$)//g
h
s/([[:blank:]]+|[^[:alnum:]])/_/g
s/(.*)/declare -A ${VARPREFIX}${SECPREFIX}\1=(/p
g
s/(.*)/ \[${SECCNAMEKEY}\]=\"\1\"/
b
}
# FIXME: This needs to pick up escaped =:s
/^([[:blank:]]*[^[:blank:]]+[[:blank:]]*)+[=:].*$/ {
# Escape any ] characters within key name - bash <4.3 can't handle them
s/^(([^\]]*)\[+)*([=:].*)$/\2\\\\\]\3/
# Escape any ' characters within the key name
s/^[[:blank:]]*/ \[\'/
s/[[:blank:]]*[=:][[:blank:]]*(.*)$/\']=\1/
########s/([\"]+)/\\\\\1/g
#s/^(\[')([']+)('\].*)/\1X\3/g
# s/[[:blank:]]*[=:][[:blank:]]*[\"\'\`]?(.*)$/\]=\'\1/
# s/^[[:blank:]]*([[:print:]]+)[[:blank:]]*[=:][[:blank:]]*/\[\1\]=/
b
}
q
}"
echo ")"
}
; initest
# Join lines ending in \ :
sed ':x; /\\$/ { N; s/\\\n//; tx }' textfile
echo 'ao ao ao | ao' | sed 'h; s/.*|/|/; x; s/|.*//; s/o/x/g; G; s/\n//'
# if a line ends with a backslash, append the next line to it
sed -e :a -e '/\\$/N; s/\\\n//; ta'
# 4.0 needs the backslash escaped AND the ] when referencing the element
06:09 <Tadgy> 40# declare -A FOOF=( ['test\]test']="test" ) ; declare -p FOOF ; printf "<%s>" "${FOOF['test\]test']}"
06:09 <shbot> declare -A FOOF='([test\\\]test]="test" )'
06:09 <shbot> <>
06:11 <Tadgy> 40# declare -A FOOF=( ['test\]test']="test" ) ; declare -p FOOF ; printf "<%s>" "${FOOF['test\\\]test']}"
06:11 <shbot> declare -A FOOF='([test\\\]test]="test" )'
06:11 <shbot> <test>
# 4.1, 4.2, 4.3 are consistent with this syntax
06:06 <Tadgy> 41# declare -A FOOF=( ['test\]test']="test" ) ; declare -p FOOF ; printf "<%s>" "${FOOF['test\]test']}"
06:06 <shbot> declare -A FOOF='(["test\\]test"]="test" )'
06:06 <shbot> <test>
06:08 <Tadgy> 42# declare -A FOOF=( ['test\]test']="test" ) ; declare -p FOOF ; printf "<%s>" "${FOOF['test\]test']}"
06:08 <shbot> declare -A FOOF='(["test\\]test"]="test" )'
06:08 <shbot> <test>
06:09 <Tadgy> 43# declare -A FOOF=( ['test\]test']="test" ) ; declare -p FOOF ; printf "<%s>" "${FOOF['test\]test']}"
06:09 <shbot> declare -A FOOF='(["test\\]test"]="test" )'
06:09 <shbot> <test>
#Works without escapes in 4.3:
06:08 <Tadgy> 43# declare -A FOOF=( ['test]test']="test" ) ; declare -p FOOF ; printf "<%s>" "${FOOF['test]test']}"
06:08 <shbot> declare -A FOOF='(["test]test"]="test" )'
06:08 <shbot> <test>
[ [ invalid-section###3 ] $$ ] $
[ invalid-section###3 ] $$X
# Squash multiple blanks and invalid chars to single _ -- s/[^[:alnum:]]+/_/g
_invalid_section_3_
# Blanks and invalid chars replaced with _ no sqash -- s/[^[:alnum:]]/_/g
_________invalid_section___3_______
# Squash multiple blanks to single _ and replace invalid chars with _ -- s/([[:blank:]]+|[^[:alnum:]])/_/g
__invalid_section___3_____
#s/[[:blank:]]*\][[:blank:]]*[^[:alnum:]]+/_/g
# s/^[[:blank:]]*\[[[:blank:]]*/declare -A ${VAR}_/
# s/[[:blank:]]*\][[:blank:]]*$/=(/
# s/(^[[:blank:]]*\[[[:blank:]]*)|([[:blank:]]*\][[:blank:]]*$)/X/g
# s/[[:blank:]]+/ /g
# s/^[[:blank:]]*\[[[:blank:]]*([[:graph:]]*)[[:blank:]]*\][[:blank:]]*$/[\1]/
l 120
# s/^[[:blank:]]*(\[|\]) [[:blank:]]*$/\1/g
# s/([^[:alnum:]]|_+)/_/g
}
}"
s/[[:blank:]]*(\[|\])[[:blank:]]*/\1/g
s/([^[:alnum:]]|_+)/_/g
label regex jump back if s was done
# s/\[_*([^]]*)/declare -A ${VAR}_\1=(/
# s/\[_*(.*)_*\].*/declare -A ${VAR}_\1=(/
# s/[[:blank:]]*\[(.*)\].*/declare -A ${VAR}_\1=(/
}
# /^(\)|declare -A)/ ! {
# s/^[[:blank:]]*/\[/
# s/[[:blank:]]*=[[:blank:]]*/\]=\"/
# s/$/\"/g
# }
}"
# Variables:
# INI_ENV_PREFIX="INI_"
# INI_GLOBAL_??="GLOBAL"
# INI_SECTION_??="SECTION"
# Options:
#
exit
/^[[:blank:]]*\[.*\]/ {
s/[[:blank:]]*\[/)\n/g
# s/(.*)\]/declare -A ${VAR}_\1=(/g
}
-e "/^[[:blank:]]*\[.*\]/ s/[[:blank:]]*\[/)\n/g; s/(.*)\]/declare -A ${VAR}_\1=(/g"
-e 's/^[[:blank:]]*\</[
sed -r \
-e '/^[[:blank:]]*(#|;|$)/ d' \
-e "1 ideclare -A ${VAR}_${TOP}=(" \
-e "/^[[:blank:]]*\[.*\]/ s/[[:blank:]]*\[/)\n/g; s/(.*)\]/declare -A ${VAR}_\1=(/g"
-e 's/^[[:blank:]]*\</[
-e "1 s/^/declare -A ${VAR}_${TOP}=(\n/" \
# if a line ends with a backslash, append the next line to it
sed -e :a -e '/\\$/N; s/\\\n//; ta'
# print the line immediately before a regexp, but not the line
# containing the regexp
sed -n '/regexp/{g;1!p;};h'
# print the line immediately after a regexp, but not the line
# containing the regexp
sed -n '/regexp/{n;p;}'
# print section of file from regular expression to end of file
sed -n '/regexp/,$p'
# print section of file between two regular expressions (inclusive)
sed -n '/Iowa/,/Montana/p' # case sensitive
# Option (-r) to make all variables read only.
# Option (-x) to export all variables.
# Option parsing.
# http://mywiki.wooledge.org/BashFAQ/035

View file

@ -0,0 +1,123 @@
#!/bin/bash
# Todo:
# Change case of variables: \L \U \E
# export SECLIST="SECTIONS"
export VARPREFIX="INI_"
export SECPREFIX="SECTION_"
export SECCNAMEKEY="%cannonical name%"
export TOPSEC="global"
initest() {
echo "declare -A ${VARPREFIX}${SECPREFIX}${TOPSEC}"
echo "${VARPREFIX}${SECPREFIX}${TOPSEC}[${SECCNAMEKEY}]=\"${TOPSEC}\""
cat test.ini | sed -r "{
/^[[:blank:]]*(#|;|$)/ d
/^[[:blank:]]*\[.*\][[:blank:]]*$/ {
s/(^[[:blank:]]*\[[[:blank:]]*|[[:blank:]]*\][[:blank:]]*$)//g ; h
s/([[:blank:]]+|[^[:alnum:]])/_/g
s/(.*)/declare -A ${VARPREFIX}${SECPREFIX}\1\n${VARPREFIX}${SECPREFIX}\1/ ; P ; g
s/(.*)/\[${SECCNAMEKEY}\]=\"\1\"/
}
/^[[:blank:]]*[[:print:]]+[[:blank:]][=:]/ {
d
}
}"
}
; initest
[ [ invalid-section###3 ] $$ ] $
[ invalid-section###3 ] $$X
# Squash multiple blanks and invalid chars to single _ -- s/[^[:alnum:]]+/_/g
_invalid_section_3_
# Blanks and invalid chars replaced with _ no sqash -- s/[^[:alnum:]]/_/g
_________invalid_section___3_______
# Squash multiple blanks to single _ and replace invalid chars with _ -- s/([[:blank:]]+|[^[:alnum:]])/_/g
__invalid_section___3_____
#s/[[:blank:]]*\][[:blank:]]*[^[:alnum:]]+/_/g
# s/^[[:blank:]]*\[[[:blank:]]*/declare -A ${VAR}_/
# s/[[:blank:]]*\][[:blank:]]*$/=(/
# s/(^[[:blank:]]*\[[[:blank:]]*)|([[:blank:]]*\][[:blank:]]*$)/X/g
# s/[[:blank:]]+/ /g
# s/^[[:blank:]]*\[[[:blank:]]*([[:graph:]]*)[[:blank:]]*\][[:blank:]]*$/[\1]/
l 120
# s/^[[:blank:]]*(\[|\]) [[:blank:]]*$/\1/g
# s/([^[:alnum:]]|_+)/_/g
}
}"
s/[[:blank:]]*(\[|\])[[:blank:]]*/\1/g
s/([^[:alnum:]]|_+)/_/g
label regex jump back if s was done
# s/\[_*([^]]*)/declare -A ${VAR}_\1=(/
# s/\[_*(.*)_*\].*/declare -A ${VAR}_\1=(/
# s/[[:blank:]]*\[(.*)\].*/declare -A ${VAR}_\1=(/
}
# /^(\)|declare -A)/ ! {
# s/^[[:blank:]]*/\[/
# s/[[:blank:]]*=[[:blank:]]*/\]=\"/
# s/$/\"/g
# }
}"
# Variables:
# INI_ENV_PREFIX="INI_"
# INI_GLOBAL_??="GLOBAL"
# INI_SECTION_??="SECTION"
# Options:
#
exit
/^[[:blank:]]*\[.*\]/ {
s/[[:blank:]]*\[/)\n/g
# s/(.*)\]/declare -A ${VAR}_\1=(/g
}
-e "/^[[:blank:]]*\[.*\]/ s/[[:blank:]]*\[/)\n/g; s/(.*)\]/declare -A ${VAR}_\1=(/g"
-e 's/^[[:blank:]]*\</[
sed -r \
-e '/^[[:blank:]]*(#|;|$)/ d' \
-e "1 ideclare -A ${VAR}_${TOP}=(" \
-e "/^[[:blank:]]*\[.*\]/ s/[[:blank:]]*\[/)\n/g; s/(.*)\]/declare -A ${VAR}_\1=(/g"
-e 's/^[[:blank:]]*\</[
-e "1 s/^/declare -A ${VAR}_${TOP}=(\n/" \
# if a line ends with a backslash, append the next line to it
sed -e :a -e '/\\$/N; s/\\\n//; ta'
# print the line immediately before a regexp, but not the line
# containing the regexp
sed -n '/regexp/{g;1!p;};h'
# print the line immediately after a regexp, but not the line
# containing the regexp
sed -n '/regexp/{n;p;}'
# print section of file from regular expression to end of file
sed -n '/regexp/,$p'
# print section of file between two regular expressions (inclusive)
sed -n '/Iowa/,/Montana/p' # case sensitive
# Option (-r) to make all variables read only.
# Option (-x) to export all variables.

View file

@ -0,0 +1,128 @@
#!/bin/bash
# Todo:
# Change case of variables: \L \U \E
# export SECLIST="SECTIONS"
export VARPREFIX="INI_"
export SECPREFIX="SECTION_"
export SECCNAMEKEY="%cannonical name%"
export TOPSEC="global"
initest() {
echo "declare -A ${VARPREFIX}${SECPREFIX}${TOPSEC}"
echo "${VARPREFIX}${SECPREFIX}${TOPSEC}+=("
echo "[${SECCNAMEKEY}]=\"${TOPSEC}\""
cat test.ini | sed -r "{
/^[[:blank:]]*(#|;|$)/ d
/^[[:blank:]]*\[.*\][[:blank:]]*$/ {
i )
s/(^[[:blank:]]*\[[[:blank:]]*|[[:blank:]]*\][[:blank:]]*$)//g
h
s/([[:blank:]]+|[^[:alnum:]])/_/g
s/(.*)/declare -A ${VARPREFIX}${SECPREFIX}\1\n${VARPREFIX}${SECPREFIX}\1+=(/
p ; g
s/(.*)/\[${SECCNAMEKEY}\]=\"\1\"/
}
/^[[:blank:]]*[[:print:]]+[[:blank:]][=:]/ {
d
}
}"
echo ")"
}
; initest
[ [ invalid-section###3 ] $$ ] $
[ invalid-section###3 ] $$X
# Squash multiple blanks and invalid chars to single _ -- s/[^[:alnum:]]+/_/g
_invalid_section_3_
# Blanks and invalid chars replaced with _ no sqash -- s/[^[:alnum:]]/_/g
_________invalid_section___3_______
# Squash multiple blanks to single _ and replace invalid chars with _ -- s/([[:blank:]]+|[^[:alnum:]])/_/g
__invalid_section___3_____
#s/[[:blank:]]*\][[:blank:]]*[^[:alnum:]]+/_/g
# s/^[[:blank:]]*\[[[:blank:]]*/declare -A ${VAR}_/
# s/[[:blank:]]*\][[:blank:]]*$/=(/
# s/(^[[:blank:]]*\[[[:blank:]]*)|([[:blank:]]*\][[:blank:]]*$)/X/g
# s/[[:blank:]]+/ /g
# s/^[[:blank:]]*\[[[:blank:]]*([[:graph:]]*)[[:blank:]]*\][[:blank:]]*$/[\1]/
l 120
# s/^[[:blank:]]*(\[|\]) [[:blank:]]*$/\1/g
# s/([^[:alnum:]]|_+)/_/g
}
}"
s/[[:blank:]]*(\[|\])[[:blank:]]*/\1/g
s/([^[:alnum:]]|_+)/_/g
label regex jump back if s was done
# s/\[_*([^]]*)/declare -A ${VAR}_\1=(/
# s/\[_*(.*)_*\].*/declare -A ${VAR}_\1=(/
# s/[[:blank:]]*\[(.*)\].*/declare -A ${VAR}_\1=(/
}
# /^(\)|declare -A)/ ! {
# s/^[[:blank:]]*/\[/
# s/[[:blank:]]*=[[:blank:]]*/\]=\"/
# s/$/\"/g
# }
}"
# Variables:
# INI_ENV_PREFIX="INI_"
# INI_GLOBAL_??="GLOBAL"
# INI_SECTION_??="SECTION"
# Options:
#
exit
/^[[:blank:]]*\[.*\]/ {
s/[[:blank:]]*\[/)\n/g
# s/(.*)\]/declare -A ${VAR}_\1=(/g
}
-e "/^[[:blank:]]*\[.*\]/ s/[[:blank:]]*\[/)\n/g; s/(.*)\]/declare -A ${VAR}_\1=(/g"
-e 's/^[[:blank:]]*\</[
sed -r \
-e '/^[[:blank:]]*(#|;|$)/ d' \
-e "1 ideclare -A ${VAR}_${TOP}=(" \
-e "/^[[:blank:]]*\[.*\]/ s/[[:blank:]]*\[/)\n/g; s/(.*)\]/declare -A ${VAR}_\1=(/g"
-e 's/^[[:blank:]]*\</[
-e "1 s/^/declare -A ${VAR}_${TOP}=(\n/" \
# if a line ends with a backslash, append the next line to it
sed -e :a -e '/\\$/N; s/\\\n//; ta'
# print the line immediately before a regexp, but not the line
# containing the regexp
sed -n '/regexp/{g;1!p;};h'
# print the line immediately after a regexp, but not the line
# containing the regexp
sed -n '/regexp/{n;p;}'
# print section of file from regular expression to end of file
sed -n '/regexp/,$p'
# print section of file between two regular expressions (inclusive)
sed -n '/Iowa/,/Montana/p' # case sensitive
# Option (-r) to make all variables read only.
# Option (-x) to export all variables.

View file

@ -0,0 +1,117 @@
#!/bin/bash
export VARPREFIX="INI_"
export SECPREFIX="SECTION_"
export SECLIST="SECTIONS"
export TOPSEC="global"
cat test.ini | sed -r "{
1 i declare -a ${VARPREFIX}${SECLIST}=( ${VARPREFIX}${SECPREFIX}${TOPSEC} )
1 i declare -A ${VARPREFIX}${SECPREFIX}${TOPSEC}=(
$ a )
/^[[:blank:]]*(#|;|$)/ d
/^[[:blank:]]*\[.*\][[:blank:]]*$/ {
i )
s/(^[[:blank:]]*\[[[:blank:]]*|[[:blank:]]*\][[:blank:]]*$)//g
s/([[:blank:]]+|[^[:alnum:]])/_/g
h ; s/(.*)/${VARPREFIX}${SECLIST}+=( \1 )/ ; p ; g
s/(.*)/declare -A ${VARPREFIX}${SECPREFIX}\1=(/
b
}
/.*=.*/ {
d
}
}"
[ [ invalid-section###3 ] $$ ] $
[ invalid-section###3 ] $$X
# Squash multiple blanks and invalid chars to single _ -- s/[^[:alnum:]]+/_/g
_invalid_section_3_
# Blanks and invalid chars replaced with _ no sqash -- s/[^[:alnum:]]/_/g
_________invalid_section___3_______
# Squash multiple blanks to single _ and replace invalid chars with _ -- s/([[:blank:]]+|[^[:alnum:]])/_/g
__invalid_section___3_____
#s/[[:blank:]]*\][[:blank:]]*[^[:alnum:]]+/_/g
# s/^[[:blank:]]*\[[[:blank:]]*/declare -A ${VAR}_/
# s/[[:blank:]]*\][[:blank:]]*$/=(/
# s/(^[[:blank:]]*\[[[:blank:]]*)|([[:blank:]]*\][[:blank:]]*$)/X/g
# s/[[:blank:]]+/ /g
# s/^[[:blank:]]*\[[[:blank:]]*([[:graph:]]*)[[:blank:]]*\][[:blank:]]*$/[\1]/
l 120
# s/^[[:blank:]]*(\[|\]) [[:blank:]]*$/\1/g
# s/([^[:alnum:]]|_+)/_/g
}
}"
s/[[:blank:]]*(\[|\])[[:blank:]]*/\1/g
s/([^[:alnum:]]|_+)/_/g
label regex jump back if s was done
# s/\[_*([^]]*)/declare -A ${VAR}_\1=(/
# s/\[_*(.*)_*\].*/declare -A ${VAR}_\1=(/
# s/[[:blank:]]*\[(.*)\].*/declare -A ${VAR}_\1=(/
}
# /^(\)|declare -A)/ ! {
# s/^[[:blank:]]*/\[/
# s/[[:blank:]]*=[[:blank:]]*/\]=\"/
# s/$/\"/g
# }
}"
# Variables:
# INI_ENV_PREFIX="INI_"
# INI_GLOBAL_??="GLOBAL"
# INI_SECTION_??="SECTION"
# Options:
#
exit
/^[[:blank:]]*\[.*\]/ {
s/[[:blank:]]*\[/)\n/g
# s/(.*)\]/declare -A ${VAR}_\1=(/g
}
-e "/^[[:blank:]]*\[.*\]/ s/[[:blank:]]*\[/)\n/g; s/(.*)\]/declare -A ${VAR}_\1=(/g"
-e 's/^[[:blank:]]*\</[
sed -r \
-e '/^[[:blank:]]*(#|;|$)/ d' \
-e "1 ideclare -A ${VAR}_${TOP}=(" \
-e "/^[[:blank:]]*\[.*\]/ s/[[:blank:]]*\[/)\n/g; s/(.*)\]/declare -A ${VAR}_\1=(/g"
-e 's/^[[:blank:]]*\</[
-e "1 s/^/declare -A ${VAR}_${TOP}=(\n/" \
# if a line ends with a backslash, append the next line to it
sed -e :a -e '/\\$/N; s/\\\n//; ta'
# print the line immediately before a regexp, but not the line
# containing the regexp
sed -n '/regexp/{g;1!p;};h'
# print the line immediately after a regexp, but not the line
# containing the regexp
sed -n '/regexp/{n;p;}'
# print section of file from regular expression to end of file
sed -n '/regexp/,$p'
# print section of file between two regular expressions (inclusive)
sed -n '/Iowa/,/Montana/p' # case sensitive

View file

@ -0,0 +1,185 @@
#!/bin/bash
# Notes:
# Cannot use any of the deliminators in the key name
# Todo:
# Lines beginning with #; within " .. " blocks on new lines will be stripped.
# Allow merging of multiple sections with the same name
# Change case of variables: \L \U \E
# export SECLIST="SECTIONS"
# Allow delims to be specified in a var - don't assume =:
export VARPREFIX="INI_"
export SECPREFIX="SECTION_"
export SECCNAMEKEY="%cannonical name%"
export TOPSEC="global"
initest() {
echo "declare -A ${VARPREFIX}${SECPREFIX}${TOPSEC}=("
echo "[${SECCNAMEKEY}]=\"${TOPSEC}\""
cat $1 | sed -r "{
# Ignore blank lines and comments
/^[[:blank:]]*(#|;|$)/ d
# Handle [section] lines
/^[[:blank:]]*\[.*\][[:blank:]]*$/ {
i )
s/(^[[:blank:]]*\[[[:blank:]]*|[[:blank:]]*\][[:blank:]]*$)//g
h
s/([[:blank:]]+|[^[:alnum:]])/_/g
s/(.*)/declare -A ${VARPREFIX}${SECPREFIX}\1=(/p
g
s/(.*)/ \[${SECCNAMEKEY}\]=\"\1\"/
b
}
# FIXME: This needs to pick up escaped =:s
/^([[:blank:]]*[^[:blank:]]+[[:blank:]]*)+[=:].*$/ {
# Escape any ] characters within key name - bash <4.3 can't handle them
s/^(([^\]]*)\[+)*([=:].*)$/\2\\\\\]\3/
# Escape any ' characters within the key name
s/^[[:blank:]]*/ \[\'/
s/[[:blank:]]*[=:][[:blank:]]*(.*)$/\']=\1/
########s/([\"]+)/\\\\\1/g
#s/^(\[')([']+)('\].*)/\1X\3/g
# s/[[:blank:]]*[=:][[:blank:]]*[\"\'\`]?(.*)$/\]=\'\1/
# s/^[[:blank:]]*([[:print:]]+)[[:blank:]]*[=:][[:blank:]]*/\[\1\]=/
b
}
q
}"
echo ")"
}
; initest
# Join lines ending in \ :
sed ':x; /\\$/ { N; s/\\\n//; tx }' textfile
echo 'ao ao ao | ao' | sed 'h; s/.*|/|/; x; s/|.*//; s/o/x/g; G; s/\n//'
# if a line ends with a backslash, append the next line to it
sed -e :a -e '/\\$/N; s/\\\n//; ta'
# 4.0 needs the backslash escaped AND the ] when referencing the element
06:09 <Tadgy> 40# declare -A FOOF=( ['test\]test']="test" ) ; declare -p FOOF ; printf "<%s>" "${FOOF['test\]test']}"
06:09 <shbot> declare -A FOOF='([test\\\]test]="test" )'
06:09 <shbot> <>
06:11 <Tadgy> 40# declare -A FOOF=( ['test\]test']="test" ) ; declare -p FOOF ; printf "<%s>" "${FOOF['test\\\]test']}"
06:11 <shbot> declare -A FOOF='([test\\\]test]="test" )'
06:11 <shbot> <test>
# 4.1, 4.2, 4.3 are consistent with this syntax
06:06 <Tadgy> 41# declare -A FOOF=( ['test\]test']="test" ) ; declare -p FOOF ; printf "<%s>" "${FOOF['test\]test']}"
06:06 <shbot> declare -A FOOF='(["test\\]test"]="test" )'
06:06 <shbot> <test>
06:08 <Tadgy> 42# declare -A FOOF=( ['test\]test']="test" ) ; declare -p FOOF ; printf "<%s>" "${FOOF['test\]test']}"
06:08 <shbot> declare -A FOOF='(["test\\]test"]="test" )'
06:08 <shbot> <test>
06:09 <Tadgy> 43# declare -A FOOF=( ['test\]test']="test" ) ; declare -p FOOF ; printf "<%s>" "${FOOF['test\]test']}"
06:09 <shbot> declare -A FOOF='(["test\\]test"]="test" )'
06:09 <shbot> <test>
#Works without escapes in 4.3:
06:08 <Tadgy> 43# declare -A FOOF=( ['test]test']="test" ) ; declare -p FOOF ; printf "<%s>" "${FOOF['test]test']}"
06:08 <shbot> declare -A FOOF='(["test]test"]="test" )'
06:08 <shbot> <test>
[ [ invalid-section###3 ] $$ ] $
[ invalid-section###3 ] $$X
# Squash multiple blanks and invalid chars to single _ -- s/[^[:alnum:]]+/_/g
_invalid_section_3_
# Blanks and invalid chars replaced with _ no sqash -- s/[^[:alnum:]]/_/g
_________invalid_section___3_______
# Squash multiple blanks to single _ and replace invalid chars with _ -- s/([[:blank:]]+|[^[:alnum:]])/_/g
__invalid_section___3_____
#s/[[:blank:]]*\][[:blank:]]*[^[:alnum:]]+/_/g
# s/^[[:blank:]]*\[[[:blank:]]*/declare -A ${VAR}_/
# s/[[:blank:]]*\][[:blank:]]*$/=(/
# s/(^[[:blank:]]*\[[[:blank:]]*)|([[:blank:]]*\][[:blank:]]*$)/X/g
# s/[[:blank:]]+/ /g
# s/^[[:blank:]]*\[[[:blank:]]*([[:graph:]]*)[[:blank:]]*\][[:blank:]]*$/[\1]/
l 120
# s/^[[:blank:]]*(\[|\]) [[:blank:]]*$/\1/g
# s/([^[:alnum:]]|_+)/_/g
}
}"
s/[[:blank:]]*(\[|\])[[:blank:]]*/\1/g
s/([^[:alnum:]]|_+)/_/g
label regex jump back if s was done
# s/\[_*([^]]*)/declare -A ${VAR}_\1=(/
# s/\[_*(.*)_*\].*/declare -A ${VAR}_\1=(/
# s/[[:blank:]]*\[(.*)\].*/declare -A ${VAR}_\1=(/
}
# /^(\)|declare -A)/ ! {
# s/^[[:blank:]]*/\[/
# s/[[:blank:]]*=[[:blank:]]*/\]=\"/
# s/$/\"/g
# }
}"
# Variables:
# INI_ENV_PREFIX="INI_"
# INI_GLOBAL_??="GLOBAL"
# INI_SECTION_??="SECTION"
# Options:
#
exit
/^[[:blank:]]*\[.*\]/ {
s/[[:blank:]]*\[/)\n/g
# s/(.*)\]/declare -A ${VAR}_\1=(/g
}
-e "/^[[:blank:]]*\[.*\]/ s/[[:blank:]]*\[/)\n/g; s/(.*)\]/declare -A ${VAR}_\1=(/g"
-e 's/^[[:blank:]]*\</[
sed -r \
-e '/^[[:blank:]]*(#|;|$)/ d' \
-e "1 ideclare -A ${VAR}_${TOP}=(" \
-e "/^[[:blank:]]*\[.*\]/ s/[[:blank:]]*\[/)\n/g; s/(.*)\]/declare -A ${VAR}_\1=(/g"
-e 's/^[[:blank:]]*\</[
-e "1 s/^/declare -A ${VAR}_${TOP}=(\n/" \
# if a line ends with a backslash, append the next line to it
sed -e :a -e '/\\$/N; s/\\\n//; ta'
# print the line immediately before a regexp, but not the line
# containing the regexp
sed -n '/regexp/{g;1!p;};h'
# print the line immediately after a regexp, but not the line
# containing the regexp
sed -n '/regexp/{n;p;}'
# print section of file from regular expression to end of file
sed -n '/regexp/,$p'
# print section of file between two regular expressions (inclusive)
sed -n '/Iowa/,/Montana/p' # case sensitive
# Option (-r) to make all variables read only.
# Option (-x) to export all variables.
# Option parsing.
# http://mywiki.wooledge.org/BashFAQ/035

41
bits/value-tests.ini Normal file
View file

@ -0,0 +1,41 @@
#####################
# Single line tests #
#####################
# No quotes, extra spaces within value.
key name 1 = key value 1
# No quotes, tab+spaces before value.
key name 2 = key value 2
# No quotes, spaces before and after value.
key name 3 = key value 3
# No quotes, extra spacing before and after value, value includes "
key name 4 =
# Double quotes, extra spaces within value.
key name 4 = "this is a line with many spaces in it"
# Single quotes, extra spaces within value.
key name 5 = 'extra spaces within value'
#
####################
# Multi line tests #
####################
key name 5 = ' this is a multiple
line entry'
key name 6 = this is a second \
multi \
line entry
key name 7 = "\
this should
all be aligned left"