我試圖讓我的代碼更干凈。我的功能似乎相當傾斜,無法進行簡單的查找/替換。有沒有更簡潔的方法可以用 awk 或類似的東西來查找/替換陣列函式?
# Finds first item in array that matches find item, and replaces it with 1 or more array elements.
# Preserves sort order of original array.
find_replace_in_list(){
# $1 = list
# $2 = find item string
# $3 = replace array.
local -n _list=$1
local -n _replace_list=$3
for i in "${!_list[@]}"; do # Iterate over indices.
if [ ${_list[$i]} == "$2" ]; then
# Insert the replace array starting at indice.
local p=$((i 1)) # Get indice just after match.
local array_pre=${_list[@]:0:i}
local array_post=${_list[@]:p}
local new_array=("${array_pre[@]}" "${_replace_list[@]}" "${array_post[@]}")
echo "${new_array[@]}"
return # Break out of loop. Only replace first match.
fi
done
# Nothing found. Return orginal array.
echo "${_list[@]}"
}
: ' Example use ^^^
list=('a' 'b' 'c' 'd')
find='b'
replace_list=('b1' 'b2' 'b3')
test=$(find_replace_in_list list "$find" replace_list)
echo "RESULT:${test[*]}"
RESULT: a b1 b2 b3 c d
'
uj5u.com熱心網友回復:
回傳另一個共享全域變數:
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
}
修改原始串列:
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
}
uj5u.com熱心網友回復:
您可以使用nameref's( declare -n) 向/從函式傳遞資料。
此外,我們不會嘗試重新索引當前陣列,而是即時構建一個新陣列(newlistaka _newlist),從而使我們能夠簡化代碼。
修改當前代碼...
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
}
測驗#1(一場比賽和替換):
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
這會產生:
declare -a newlist=([0]="a" [1]="b1" [2]="b2" [3]="b3" [4]="c" [5]="d")
測驗#2(未找到匹配項):
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
這會產生:
declare -a newlist=([0]="a" [1]="b" [2]="c" [3]="d")
測驗#3a(一場比賽和替換):
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
這會產生:
declare -a newlist=([0]="a" [1]="b" [2]="c7" [3]="c8" [4]="c9" [5]="d" [6]="c")
測驗#3b(最多允許 999 個匹配和替換):
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
這會產生:
declare -a newlist=([0]="a" [1]="b" [2]="c7" [3]="c8" [4]="c9" [5]="d" [6]="c7" [7]="c8" [8]="c9")
uj5u.com熱心網友回復:
您可以將陣列作為結果回傳stdout,readarray但它會派生一個子外殼:
#!/usr/bin/env bash
# Finds first item in array that matches find item, and replaces it with 1 or more array elements.
# Preserves sort order of original array.
find_replace_in_list() {
# $1 = list
# $2 = find item string
# $3 = replace array.
local -n _list=$1
local -n _replace_list=$3
for i in "${!_list[@]}"; do # Iterate over indices.
if [ "${_list[$i]}" == "$2" ]; then
# Insert the replace array starting at indice.
local p=$((i 1)) # Get indice just after match.
local new_array=("${_list[@]:0:i}" "${_replace_list[@]}" "${_list[@]:p}")
printf '%s\0' "${new_array[@]}"
return # Break out of loop. Only replace first match.
fi
done
# Nothing found. Return orginal array.
echo "${_list[@]}"
}
# shellcheck disable=SC2034 # nameref use
list=('a' 'b' 'c' 'd')
find='b'
# shellcheck disable=SC2034 # nameref use
replace_list=('b1' 'b2' 'b3')
readarray -td '' test < <(find_replace_in_list list "$find" replace_list)
printf 'RESULT: %s\n' "${test[*]}"
或者您可以回傳新陣列作為參考:
#!/usr/bin/env bash
# Finds first item in array that matches find item, and replaces it with 1 or more array elements.
# Preserves sort order of original array.
find_replace_in_list() {
# $1 = list nameref
# $2 = find item string
# $3 = replace array.nameref
# ?$4 = optional new array nameref
local -n _list=$1
local -n _replace_list=$3
if [ $# -eq 4 ]; then
local -n _new_list=$4
else
local -a _new_list=()
fi
for i in "${!_list[@]}"; do # Iterate over indices.
if [ "${_list[$i]}" == "$2" ]; then
# Insert the replace array starting at indice.
local p=$((i 1)) # Get indice just after match.
_new_list=("${_list[@]:0:i}" "${_replace_list[@]}" "${_list[@]:p}")
# If no new array reference, print null delimited
[ $# -lt 4 ] && printf '%s\0' "${_new_list[@]}"
return # Break out of loop. Only replace first match.
fi
done
# Nothing found. Return orginal array.
echo "${_list[@]}"
}
# shellcheck disable=SC2034 # nameref use
list=('a' 'b' 'c' 'd')
find='b'
# shellcheck disable=SC2034 # nameref use
replace_list=('b1' 'b2' 'b3')
find_replace_in_list list "$find" replace_list test
# shellcheck disable=SC2154 # nameref use
printf 'RESULT: %s\n' "${test[*]}"
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/420662.html
標籤:
