Last active
January 7, 2022 23:00
-
-
Save konsolebox/b92e4df366476ee43652adb3b1dba374 to your computer and use it in GitHub Desktop.
Provides a function that emulates bash 5.0's mapfile
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
#!/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