Skip to content

Instantly share code, notes, and snippets.

@konsolebox
Last active January 7, 2022 23:00
Show Gist options
  • Save konsolebox/b92e4df366476ee43652adb3b1dba374 to your computer and use it in GitHub Desktop.
Save konsolebox/b92e4df366476ee43652adb3b1dba374 to your computer and use it in GitHub Desktop.
Provides a function that emulates bash 5.0's mapfile
#!/bin/bash
shopt -s extglob
[[ BASH_VERSINFO -ge 5 ]] && set -u
#### Implementation Snippet Begins ####
function mapfile.error {
printf '%s\n' "$1" "$@"
exit "${2-1}"
}
function mapfile {
local -a __opts __delim __callback __array
local __max=0 __origin=0 __skip=0 __remove_trailing=false __fd=0 __quantum=5000 __append=
local __i __j __
__opts=("$@")
__array=()
while [[ $# -gt 0 ]]; do
case $1 in
-d)
__delim=$2
shift
;;
-n)
[[ ${2-} == +([[:digit:]]) ]] || mapfile.error "Invalid argument to '$1': ${2-}"
__max=$2
shift
;;
-O)
[[ ${2-} == +([[:digit:]]) ]] || mapfile.error "Invalid argument to '$1': ${2-}"
__origin=$2
shift
;;
-s)
[[ ${2-} == +([[:digit:]]) ]] || mapfile.error "Invalid argument to '$1': ${2-}"
__skip=$2
shift
;;
-t)
__remove_trailing=true
;;
-u)
[[ ${2-} == +([[:digit:]]) ]] || mapfile.error "Invalid argument to '$1': ${2-}"
__fd=$2
shift
;;
-C)
[[ ${2+.} ]] || mapfile.error "Invalid argument to '$1': ${2-}"
__callback=$2
shift
;;
-c)
[[ ${2-} == +([[:digit:]]) && $2 -gt 0 ]] || \
mapfile.error "Invalid argument to '$1': ${2-}"
__quantum=$2
shift
;;
--)
__array=("${__array[@]}" "${@:2}")
break
;;
-*)
mapfile.error "Invalid option: $1"
;;
*)
__array=("${__array[@]}" "$1")
;;
esac
shift
done
for __ in "${__array[@]}"; do
[[ $__ == +([[:alpha:]_])*([[:alnum:]_]) ]] || \
mapfile.error "Invalid non-variable argument: $__"
done
[[ ${#__array[@]} -gt 1 ]] && mapfile.error "Too many variables specified."
if [[ -z ${__delim+.} && BASH_VERSINFO -ge 4 ]]; then
builtin mapfile "${__opts[@]}"
return
fi
__delim=${__delim-$'\n'}
__array=${__array-MAPFILE}
eval "$__array=()"
if [[ __skip -gt 0 ]]; then
while (( __skip-- > 0 )); do
IFS= read -rd "$__delim" -u "$__fd" __ || return
done
fi
[[ __max -eq 0 ]] && __max=-1
[[ $__remove_trailing == false ]] && __append=$__delim
for (( __i = ${__origin-0}, __j = 0; __j++ != __max; )); do
IFS= read -rd "$__delim" -u "$__fd" __ || break
__=$__$__append
(( __j % __quantum == 0 )) && [[ ${__callback+.} ]] && "$__callback" "$__i" "$__"
eval "$__array[__i++]=\$__"
done
}
function readarray {
mapfile "$@"
}
#### Implementation Snippet Ends ####
mapfile "$@"
declare -p MAPFILE
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment