Find Item in Array / Replace With Array Using Awk?
Return to another shared global variable:
find_replace_in_list() {
local -n _list=$1 _replace_list=$3
__A0=()
for i in "${!_list[@]}"; do
if [[ ${_list[i]} == "$2" ]]; then
__A0+=("${_replace_list[@]}" "${_list[@]:i + 1}")
break
fi
__A0[i]=${_list[i]}
done
}
Modify original list:
find_replace_in_list() {
local -n _list=$1 _replace_list=$3
local counter=0
for i in "${!_list[@]}"; do
if [[ ${_list[i]} == "$2" ]]; then
_list=("${_list[@]:0:counter}" "${_replace_list[@]}" "${_list[@]:i + 1}")
break
fi
(( ++counter ))
done
}
You can use nameref's
(declare -n
) to pass data to/from the function.
Also, instead of trying to reindex a current array we'll just build a new array (newlist
aka _newlist
) on-the-fly thus allowing us to simplify the code.
Modifying the current code ...
find_replace_in_list(){
# $1 = list (array) : read from
# $2 = find item (string)
# $3 = replace list (array) : read from
# $4 = newlist (array) : write to
# $5 = number of times to match-n-replace (optional; default=1)
local -n _list=$1
local ptn=$2
local -n _replace_list=$3
local -n _newlist=$4
local match_count=${5:-1} # OP can add more logic to validate $5 is a positive integer
_newlist=()
for item in "${_list[@]}"
do
if [[ "${item}" = "${ptn}" && "${match_count}" -gt 0 ]]
then
_newlist+=( "${_replace_list[@]}" )
(( match_count-- ))
else
_newlist+=( "${item}" )
fi
done
}
Test #1 (one match & replacement):
list=('a' 'b' 'c' 'd')
find='b'
replace_list=('b1' 'b2' 'b3')
newlist=()
find_replace_in_list list "$find" replace_list newlist
typeset -p newlist
This generates:
declare -a newlist=([0]="a" [1]="b1" [2]="b2" [3]="b3" [4]="c" [5]="d")
Test #2 (no matches found):
list=('a' 'b' 'c' 'd')
find='z'
replace_list=('z1' 'z2' 'z3')
newlist=()
find_replace_in_list list "$find" replace_list newlist
typeset -p newlist
This generates:
declare -a newlist=([0]="a" [1]="b" [2]="c" [3]="d")
Test #3a (one match & replacement):
list=('a' 'b' 'c' 'd' 'c')
find='c'
replace_list=('c7' 'c8' 'c9')
newlist=()
find_replace_in_list list "$find" replace_list newlist
typeset -p newlist
This generates:
declare -a newlist=([0]="a" [1]="b" [2]="c7" [3]="c8" [4]="c9" [5]="d" [6]="c")
Test #3b (allow up to 999 match & replacements):
list=('a' 'b' 'c' 'd' 'c')
find='c'
replace_list=('c7' 'c8' 'c9')
newlist=()
find_replace_in_list list "$find" replace_list newlist 999
typeset -p newlist
This generates:
declare -a newlist=([0]="a" [1]="b" [2]="c7" [3]="c8" [4]="c9" [5]="d" [6]="c7" [7]="c8" [8]="c9")