Permalink
Browse files

initial commit awc_bash_ini_parser-0.3.tgz

  • Loading branch information...
0 parents commit bce351a83a6296da4ba50b5b9b83f294bb541078 @rudimeier committed Dec 8, 2010
Showing with 734 additions and 0 deletions.
  1. +101 −0 README
  2. +7 −0 TODO
  3. +237 −0 read_ini.sh
  4. +28 −0 test/test.sh
  5. +40 −0 test/test1.ini
  6. +10 −0 test/test1.out.correct
  7. +21 −0 test/test1.sh
  8. +8 −0 test/test2.ini
  9. +2 −0 test/test2.out.correct
  10. +8 −0 test/test2.sh
  11. +23 −0 test/test3.ini
  12. +12 −0 test/test3.out.correct
  13. +25 −0 test/test3.sh
  14. +14 −0 test/test4.ini
  15. +5 −0 test/test4.out.correct
  16. +15 −0 test/test4.sh
  17. +5 −0 test/test5.ini
  18. +2 −0 test/test5.out.correct
  19. +13 −0 test/test5.sh
  20. +27 −0 test/test6.ini
  21. +30 −0 test/test6.out.correct
  22. +56 −0 test/test6.sh
  23. +8 −0 test/test7.ini
  24. +7 −0 test/test7.out.correct
  25. +30 −0 test/test7.sh
101 README
@@ -0,0 +1,101 @@
+
+COPYRIGHT
+=========
+
+Copyright (c) 2009 Kevin Porter / Advanced Web Construction Ltd
+(http://coding.tinternet.info / http://webutils.co.uk)
+
+
+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
+
+
+
7 TODO
@@ -0,0 +1,7 @@
+
+
+- Tabs/newlines to be preserved
+
+- [] notation for arrays (like PHP's parse_ini_file())
+
+
@@ -0,0 +1,237 @@
+#
+# Copyright (c) 2009 Kevin Porter / Advanced Web Construction Ltd
+# (http://coding.tinternet.info, http://webutils.co.uk)
+#
+# Simple INI file parser.
+#
+# See README for usage.
+#
+#
+
+
+function read_ini()
+{
+
+ local INI_FILE=""
+ local INI_SECTION=""
+
+ # {{{ START Deal with command line args
+
+ # Set defaults
+ local BOOLEANS=1
+ local VARNAME_PREFIX=INI
+
+ # {{{ 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
+
+ --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" ]
+ then
+ echo "Usage: read_ini FILE [SECTION]" >&2
+ return 1
+ fi
+
+ if [ ! -f "$INI_FILE" ]
+ then
+ echo "Error: ini file '${INI_FILE}' doesn't exist" >&2
+ return 1
+ fi
+
+ # Be strict with the prefix, since it's going to be run through eval
+ local PREFIX_BANNED_CHARS=$(echo "$VARNAME_PREFIX" | sed 's/[a-z0-9_]//ig')
+
+ if [ -n "$PREFIX_BANNED_CHARS" ]
+ then
+ echo "Invalid characters ('${PREFIX_BANNED_CHARS}') in variable name prefix ('${VARNAME_PREFIX}')" >&2
+ return 1
+ fi
+
+ # Prefix can't start with a number
+ local FIRSTCHAR=${VARNAME_PREFIX:0:1}
+ local BEGINS_WITH_NUMBER=""
+ case $FIRSTCHAR in
+ 0|1|2|3|4|5|6|7|8|9)
+ echo "Invalid variable name prefix - must not begin with a number" >&2
+ return 1
+ ;;
+ esac
+
+ # 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=""
+ while read 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?
+ local line_rev=$(echo "$line" | rev)
+ if [ "${line:0:1}" = "[" ] && [ "${line_rev:0: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 '=')
+ local VAR_VAL=$(echo "$line" | awk 'BEGIN { FS="=" } /^[a-zA-Z0-9._-]+[[:space:]]*=/ { print $1,"__INI__PARSER__DELIMITER__",$2; }')
+#echo "VAR_VAL = *$VAR_VAL*"
+
+ if [ -z "$VAR_VAL" ]
+ then
+ echo "Error: Invalid line:" >&2
+ echo " ${LINE_NUM}: $line" >&2
+ return 1
+ fi
+
+ local VAR=$(echo "$VAR_VAL" | awk -F__INI__PARSER__DELIMITER__ '{print $1}')
+ local VAL=$(echo "$VAR_VAL" | awk -F__INI__PARSER__DELIMITER__ '{sub(/^[[:space:]]+/,"",$2); print $2;}')
+ VAR=$(echo $VAR)
+#echo VAL = $VAL
+
+
+ # 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
+
+ # Surround VAL with quotes if it isn't already
+ local FIRSTCHAR=${VAL:0:1}
+ local LASTCHAR=${VAL:$LEN-1:1}
+ local DOUBLEQUOTES=""
+ local SINGLEQUOTES=""
+
+ if [ "$FIRSTCHAR" = '"' -a "$LASTCHAR" = '"' ]
+ then
+ DOUBLEQUOTES=1
+ fi
+
+ if [ "$FIRSTCHAR" = "'" -a "$LASTCHAR" = "'" ]
+ then
+ SINGLEQUOTES=1
+ fi
+
+ if [ -z "$SINGLEQUOTES" -a -z "$DOUBLEQUOTES" ]
+ then
+ # Value is not enclosed in quotes
+
+ # If we have booleans processing switched on, check for special boolean
+ # values and convert
+ if [ "$BOOLEANS" == 1 ]
+ then
+
+ # Check length of string first. Since we're going to use tr command to convert
+ # the string to lowercase, it'll be more efficient if we check string length
+ # first. If value is more than 5 chars then it can't possibly be one of the
+ # special boolean values
+ if [ "${#VAL}" -le 5 ]
+ then
+
+ # Convert to lower case
+ local VAL_LOWER=$(echo "$VAL" | tr '[:upper:]' '[:lower:]')
+
+ case "$VAL_LOWER" in
+ yes | true | on )
+ VAL=1
+ ;;
+ no | false | off )
+ VAL=0
+ ;;
+ esac
+ fi
+
+ fi
+
+ # We'll enclose the value in double quotes now, so we must escape any
+ # double quotes that may be in the value first
+ VAL=$(echo "$VAL" | awk '{sub(/"/,"\\\"",$0); print $0;}')
+ VAL="\"$VAL\""
+ fi
+
+ # Replace $ and ` to prevent code running inside eval
+ VAL=${VAL//\`/\\\`}
+ VAL=${VAL//\$/\\\$}
+#declare -x $VARNAME="$VAL"
+ eval "$VARNAME=$VAL"
+ done < <(cat $INI_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"
+
+
Oops, something went wrong.

0 comments on commit bce351a

Please sign in to comment.