Last active
December 13, 2015 18:18
-
-
Save hypersoft/4953906 to your computer and use it in GitHub Desktop.
Automatic I/O loop executive with environment sanitation, predefined macro source expansion, and optional script output to file, for consecutive cached calls / common operations / examination. The generated script, or executed function takes multiple files, or stdin as its arguments.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
lib.input.file.forEach () | |
{ | |
# BOOT STRAPS | |
[[ "$1$2$3" == --buildprintfxchar ]] && { | |
echo "builtin printf -- '\\x`builtin printf '%02X' "'${4}"`';"; | |
return; | |
} | |
[[ "$1$2$3" == --buildparservars ]] && { | |
declare IFS='' | |
echo "declare FILE=\"\";" | |
echo "declare RS=\"\$(`$FUNCNAME --build printf xchar ${RS:-$'\n'}`)\"; " | |
echo "declare -i IRL=0 RL=${RL:-1} RC=0 FNO=0 SPOS=0 FPOS=0 EOF=0 EOS=0; " | |
echo "declare -a TRAP[0]=\"true\";" | |
return; | |
} | |
[[ $1 == --build ]] && { "$FUNCNAME: $1 $2" || return; } | |
[[ "$1$2$3" == --listparservars ]] && { | |
echo FILE RS IRL RL RC FNO SPOS FPOS EOF EOS TRAP\; | |
return; | |
} | |
[[ "$1$2$3" == --listinternalvars ]] && { | |
echo _RECALL_{LABEL,INIT,SCRIPT,THIS,EXACT,EXPORT,HEAD,RECORD_AS}; | |
return; | |
} | |
[[ $1 == --list ]] && { "$FUNCNAME: $1 $2" || return; } | |
#MACRO SECTION, transforms %identifier to 'var label' | |
[[ "$1$2" == --parseidentifiers ]] && { | |
declare -u ID="$3"; | |
IFS= declare SCRIPT="$(< /dev/stdin)" | |
SCRIPT="${SCRIPT//\%record\.length/IRL}"; | |
SCRIPT="${SCRIPT//\%match/BASH_REMATCH}"; | |
SCRIPT="${SCRIPT//\%record\.number/RC}"; | |
SCRIPT="${SCRIPT//\%record/$ID}"; | |
SCRIPT="${SCRIPT//\%source\.position/FPOS}"; | |
SCRIPT="${SCRIPT//\%source\.end/EOF}"; # boolean 1 true: last record | |
SCRIPT="${SCRIPT//\%source/FILE}"; | |
SCRIPT="${SCRIPT//\%stream\.number/FNO}"; | |
SCRIPT="${SCRIPT//\%stream\.count/#}"; | |
SCRIPT="${SCRIPT//\%stream\.position/SPOS}"; | |
SCRIPT="${SCRIPT//\%stream\.end/EOS}"; # boolean 1 true: last source file | |
SCRIPT="${SCRIPT//\%stream/@}"; | |
printf %s "${SCRIPT}"; | |
return; | |
} | |
[[ $1 == --parse ]] && { "$FUNCNAME: $1 $2" || return; } | |
# END BOOT STRAPS | |
declare -u _RECALL_LABEL=$1 || return; shift; | |
declare -i _RECALL_EXPORT=0; | |
declare $_RECALL_LABEL='' _RECALL_INIT='' _RECALL_SCRIPT='' \ | |
_RECALL_EXACT="IFS=''" _RECALL_HEAD='' || return; | |
declare _RECALL_THIS=$(declare NOW=`date +%s`; | |
printf %08X $(( SECONDS * RANDOM )) | |
printf -- .%08X \ | |
$(( ( RANDOM * 314 ) + NOW )) \ | |
$(( SECONDS * RANDOM )) \ | |
$(( ( RANDOM * $$ ) + NOW )); | |
printf '\n'; | |
); | |
# These are the types of processing loops that are predefined. | |
if [[ $_RECALL_LABEL == RECORD ]]; then declare _RECALL_RECORD_AS='-rd"$RS"'; | |
elif [[ $_RECALL_LABEL == LINE ]]; then | |
declare _RECALL_RECORD_AS='-rd"$RS"'; | |
builtin printf -vRS '\n'; | |
elif [[ $_RECALL_LABEL == CHUNK ]]; then declare _RECALL_RECORD_AS='-rN${RL}'; | |
elif [[ $_RECALL_LABEL == CHAR ]]; then declare _RECALL_RECORD_AS='-rN1'; | |
elif [[ $_RECALL_LABEL == FORMAT ]]; then declare _RECALL_RECORD_AS="$2"; | |
else "$FUNCNAME $_RECALL_LABEL:"; return; fi; | |
[[ $_RECALL_RECORD_AS == "$1" ]] && shift; | |
# baked means: read will interpret backslashes | |
if [[ $1 == baked ]]; then | |
shift; | |
_RECALL_RECORD_AS=${_RECALL_RECORD_AS/-r/-}; | |
fi; | |
# opposite of baked | |
if [[ $1 == raw ]]; then | |
shift; | |
"$FUNCNAME: raw is implied, and cannot be reversed" || return; | |
fi; | |
declare FILE="" RS=${RS:-`builtin printf '\n'`}; | |
declare -i IRL=0 RL=${RL:-1} RC=0 FNO=0 SPOS=0 FPOS=0 EOF=0 EOS=0; | |
declare -a TRAP; | |
if [[ $_RECALL_LABEL =~ ^(RECORD|CHUNK|FORMAT)$ ]]; then | |
while [[ $2 == '=' && $# -ge 3 ]]; do | |
if [[ "$1$2" == 'delimiter=' ]]; then | |
builtin printf -vRS "%b" "$3" || return; | |
shift 3; | |
continue; | |
fi; | |
if [[ "$1$2" == 'length=' ]]; then | |
builtin printf -vRL "%i" "$3" || return; | |
shift 3; | |
continue; | |
fi; | |
"$FUNCNAME: $_RECALL_LABEL: unknown declaration: $1 $2 $3" || return; | |
break; | |
done; | |
fi; | |
[[ $1 == -i ]] && { | |
shift; (( $# )) || "$FUNCNAME: option -i: missing script argument" || return | |
(( ${#1} )) || "$FUNCNAME: option -i: invalid argument: \`'" || return; | |
builtin printf -v _RECALL_INIT %s "${1}"; shift; | |
} | |
while [[ $# -ne 0 && ${1:0:2} == -a ]]; do | |
shift; (( $# )) || "$FUNCNAME: option -a: missing script argument" || return; | |
(( ${#1} )) || "$FUNCNAME: option -a: invalid argument: \`'" || return; | |
builtin printf -v _RECALL_SCRIPT %s\\n "${_RECALL_SCRIPT}${1}"; | |
shift; | |
done; | |
[[ -z "$_RECALL_SCRIPT" ]] && { # don't sleep on me | |
(( $# )) || "$FUNCNAME: default: missing script argument" || return; | |
(( ${#1} )) || "$FUNCNAME: option default: invalid argument: \`'" || return; | |
builtin printf -v _RECALL_SCRIPT %s "${1}"; | |
shift; | |
} | |
_RECALL_SCRIPT="$( | |
{ IFS='' echo -En "$_RECALL_SCRIPT"; } | \ | |
$FUNCNAME --parse identifiers $_RECALL_LABEL | |
)"; | |
[[ $1 == -- ]] || { | |
[[ $1 == -o ]] && { | |
_RECALL_THIS="$2"; | |
_RECALL_HEAD="#!`type -p bash`"$'\n\n'"`$FUNCNAME --build parser vars;`"; | |
_RECALL_EXPORT=1; | |
} | |
} && shift; | |
[[ $_RECALL_EXPORT == 1 ]] || { | |
_RECALL_HEAD="rm $_RECALL_THIS;"$'\n'"unset -v ` | |
$FUNCNAME --list internal vars`;" | |
} | |
cat <<EOF > $_RECALL_THIS | |
$_RECALL_HEAD | |
new.shared.return.trap () | |
{ | |
TRAP[\${#TRAP[@]}]="\${*}"; | |
} | |
# custom init section for autotrap ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
# new.shared.return.trap 'echo user trap' | |
$_RECALL_INIT | |
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
$_RECALL_THIS () | |
{ | |
$_RECALL_SCRIPT | |
} | |
_auto_return_trap () { | |
unset -f $_RECALL_THIS new.shared.return.trap; | |
unset -f \$FUNCNAME; | |
unset -v TRAP; | |
} | |
new.shared.return.trap _auto_return_trap; | |
builtin trap 'for trap in "\${TRAP[@]}"; do eval \$trap; done; unset trap' RETURN; | |
for FILE in "\${@:-/dev/stdin}"; do | |
let FPOS=0 EOF=0 FNO++; | |
(( (\$# - FNO) == 0 )) && let EOS=1; | |
while (( ! EOF )); do | |
$_RECALL_EXACT builtin read $_RECALL_RECORD_AS $_RECALL_LABEL || EOF=1; | |
let IRL=\$((\${#$_RECALL_LABEL})); | |
{ (( EOF == 1 )) && (( FPOS == 0 )) && (( IRL == 0 )); } || { | |
let IRL++; # count delimiter | |
let FPOS+=\$IRL SPOS+=\$IRL RC++ | |
let IRL--; # restore length | |
} | |
# execute parser | |
$_RECALL_THIS || { declare -i e=\$?; | |
return \$e 2>/dev/null || exit \$e; | |
} | |
done < "\$FILE"; | |
done | |
EOF | |
[[ $_RECALL_EXPORT == 1 ]] || { builtin source $_RECALL_THIS "$@"; return; } | |
} |
The above generated source is from a prior version of this code.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Automatically generated I/O parser. Methods can be custom defined by delimiter or length. char, chunk and line are popular methods. Demonstration of line method follows.
The parser tries to keep track of bytes read, and records read, attempting to read source from a list of file parameters or stdin. If an output file is not specified, a temporary file is created, and the data is sourced from that file, otherwise, an -o option specifies a new script resource exhibiting its own behavior. lib.input.file.forEach bootstraps itself by performing a regular expression match and replace on auto-exported source environment variables. The %ish variable names are special to the function shortcuts for the declared environment.
$ lib.input.file.forEach '(( %- )) && echo -E$%_ || echo -En $ %_;' -o /dev/stdout;