Documentation. Clean up directory.

This commit is contained in:
Darren 'Tadgy' Austin 2019-07-21 01:28:46 +01:00
commit 30771b4471
51 changed files with 101 additions and 2468 deletions

View file

@ -1,3 +1,97 @@
Bash INI File Parser
====================
This is my attempt at a Bash INI File Parser. It's probably not elegant,
certainly not fast, but it does implement a large set of options and features.
I started work on this parser simply because I couldn't find an existing example
that wasn't just a hack, incomplete or didn't have the features I expected from
a decent parser. I hope I've come up with something helpful for other people,
but it's scratched a personal itch and I'll be using it in my future projects.
Features of the parser include:
* Global properties section.
* Unlimited custom section names to contain any number of properties.
* Section and keys can be case sensitive, or converted to upper/lower case.
* Line comments.
* Duplicate key handling - duplicate keys can be handled in 2 different ways.
* Custom bound delimiter.
* Booleans.
* ... and more!
Usage
=====
The basic usage of the parser is: `parse_ini [options] <INI file>`.
The `[options]` can be seen using `parse_ini --help` and have detailed
descriptions.
The parser outputs Bash syntax associative array declarations, and array
element definitions to `stdout`. These Bash commands can be `eval`ed into
a script to provide access to every element in the INI file. For example,
using `eval "$(parse_ini test.ini)"` in your script would define a set of
arrays whose values can be accessed in the Bash standard method, using the keys
from the INI file.
The functions from the `parse_ini` script can be included in your own scripts to
provide INI file parsing abilities.
INI File Format
===============
The INI file format is a very loose format - there are many options and features
which can be supported. I've tried to implement the widest set of features I
can, but there may be functionality missing. Some features are only available
by enabling them as a `--option`. See the output of `parse_ini --help` for the
options.
The main features of the supported INI file format are as follows:
#........1.........2.........3.........4.........5.........6.........7.........8
General File Format
-------------------
* Blank lines are ignored and can be used to separate sections/properties for
easy reading.
* After leading whitespace removal, lines beginning with `#` or `;` are treated
as comments and ignored during parsing. Comments must appear on a line on
their own.
* Escaping of shell special characters is not required.
[section] format
----------------
* Section names must only be comprised of alphanumeric characters, plus _.-+
* The .-+ characters in section names will be converted to _
* Section names are case sensitive (unless --ignore-case? is used), so 'Foo' and 'foo' are different sections.
* Whitespace is ignored before and after the section name.
* Section names should not be quoted in any way.
Keys
----
* Keys must only be comprised of alphanumeric characters, plus _.-+
* Keys should not be quoted in any way.
Values
------
Values can optionally be bookmarked with single or double quotes.
- If quotes are to be used, they must be the first and last characters of the value
- Whitespace within the quotes is retained verbatim.
- Backslash line continuation is supported within quotes (but leading whitespace on subsequent lines is removed).
Values can be continued by use of \ in the last column.
- Subsequent lines are subject to leading whitespace removal as normal.
- Comments are not recognised on subsequent lines - they are treated as part of the value.
Booleans
--------
* no_<option> sets it to 0/false, else 1/true.
* Later settings of the same key override previous ones - last one wins.
Quotes
------
* Quotes are not required for section names, keys or values. However, in some cases, quotes around the value may be required; for example, when the value begins or ends with whitespace which should be retained in the value - a set of quotes (either "..." or '...') should be used around the value.
* Quotes are not required and should not be used around section names or keys.
* If the value is within quotes ("" or ''), any use of the same quote character (either " or ') must be backslash escaped.
# http://en.wikipedia.org/wiki/INI_file:
# * Provides a good explanation of the ini format - use this for docs *
# * INI's have 'sections' and 'properties'. Properties have key = value format *
@ -34,58 +128,10 @@
# Any leading/trailing spaces/tabs between the []s and name will be removed.
General file format
-------------------
* Blank lines are ignored.
* Lines starting with # and ; (configurable), after leading whitespace removal, are treated as comments.
- Comments must appear on their own line.
Values can optionally be bookmarked with single or double quotes.
- If quotes are to be used, they must be the first and last characters of the value
- Occurances of the bookending quotes to be used within the value must be \ escaped. ???
- Whitespace within the quotes is retained verbatim.
- Backslash line continuation is supported within quotes (but leading whitespace on subsequent lines is removed).
Values can be continued by use of \ in the last column.
- Subsequent lines are subject to leading whitespace removal as normal.
- Comments are not recognised on subsequent lines - they are treated as part of the value.
Escaping of shell special characters is not required. ???
[section] format
----------------
* Section names must only be comprised of alphanumeric characters, plus _.-+
* The .-+ characters in section names will be converted to _
* Section names are case sensitive (unless --ignore-case? is used), so 'Foo' and 'foo' are different sections.
* Whitespace is ignored before and after the section name.
Booleans
--------
* no_<option> sets it to 0/false, else 1/true.
* Later settings of the same key override previous ones - last one wins.
ToDo
----
--check
Check/validate the INI file by running it through the parser. Testing the
ini file will report any problems or syntax errors in the file, but will
not set up the environment variables as would happen in normal parsing.
Any parse errors are reported to stderr. When combined with the --debug
option, every detail of the parsing process is reported to stderr.
# -c, --check-only Only validate the ini file, don't parse it into the environment
# --check Parse the file, report any problems, but don't output the code.
--debug
Show full details of the ini file parsing process. Detail is written to
stderr. Unless --check is used with this option, the parser will still
set up the environment as would happen normally,
# --debug Show all details of the parsing process to stderr. If --check is used, no code is outputted.
# --?? Set comment characters. Each char can be used to indicate a comment.
# --?? Treat all problems as errors and stop processing at that point. Need to integrate into code.
What happens if:
"[ section ]"
[ "section" ]
TODO
====
* Specific section parsing: only parse specified section(s) given on the command
line (separate by commas?). For the global section, use `.`. For every
section but global, use `*`.
* Allow changing the characters accepted as comments in the INI file.
* Allow the key/value deliminator to be more than one character.

14
TODO
View file

@ -1,14 +0,0 @@
-s <list>, --section=<list>Only parse the specified section(s). List multiple
sections seperated by commas. For the global section
use '.'. For every section except global, use '*'.
For every section including the global section, don't
use this option (or use '.,*').
--ignore-errors Ignore parse errors in the ini file and continue
processing. This will cause options to be ignored
and whole sections to be skipped if errors are found.
This option should not be used except for debugging.
* Allow changing the characters accepted as comments in the INI file.
* Allow the key/value deliminator to be more than one character?

View file

@ -1,42 +0,0 @@
# 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

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

View file

@ -1,314 +0,0 @@
#######################################################
# 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

@ -1,234 +0,0 @@
#!@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[@]}"

View file

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

View file

@ -1,118 +0,0 @@
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

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

View file

@ -1,272 +0,0 @@
#
# 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

@ -1,28 +0,0 @@
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

@ -1,40 +0,0 @@
; 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

@ -1,10 +0,0 @@
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

@ -1,21 +0,0 @@
# 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

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

View file

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

View file

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

View file

@ -1,23 +0,0 @@
; 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

@ -1,12 +0,0 @@
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

@ -1,25 +0,0 @@
# 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

@ -1,14 +0,0 @@
; 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

@ -1,5 +0,0 @@
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

@ -1,15 +0,0 @@
# 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

@ -1,13 +0,0 @@
; 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

@ -1,6 +0,0 @@
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

@ -1,16 +0,0 @@
# 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

@ -1,27 +0,0 @@
; 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

@ -1,30 +0,0 @@
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

@ -1,56 +0,0 @@
# 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

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

View file

@ -1,7 +0,0 @@
# 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

@ -1,30 +0,0 @@
# 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

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

View file

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

View file

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

View file

@ -1,12 +0,0 @@
; 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

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

View file

@ -1,16 +0,0 @@
# 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

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

View file

@ -1,34 +0,0 @@
{ 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
}"

View file

@ -1,76 +0,0 @@
#!/bin/bash
shopt -s extglob
exec {FD}<readline.ini
key2value() {
KEY="$1"
if [[ "${VALUE:0:1}" =~ [\"\'] ]]; then
printf "%s" "${VALUE:1:-1}"
else
printf "%s" "$VALUE"
fi
}
while :; do
# LINE=""
unset 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

@ -1,18 +0,0 @@
# 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

@ -1,23 +0,0 @@
#!/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

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

View file

@ -1,7 +0,0 @@
[section 1]
[section 2]
[ section 3 ]
[ section 4
[]
[ ]
[ ]

View file

@ -1,185 +0,0 @@
#!/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

@ -1,123 +0,0 @@
#!/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

@ -1,128 +0,0 @@
#!/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

@ -1,117 +0,0 @@
#!/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

@ -1,185 +0,0 @@
#!/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

@ -1,41 +0,0 @@
#####################
# 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"