You can get the number of operation down ever so slightly, and skip the call to seq:
for (( i = 1; i < ${#myarr[@]} - 1; ++i )); do
newarr+=( "${myarr[i]}" "${myarr[i]}" )
done
newarr=( "${myarr[0]}" "${newarr[@]}" "${myarr[-1]}" )
This assumes that newarr is empty to start with. Do unset newarry first if it's not.
As a function (this modifies the array that is passed):
dup_interal_items () {
typeset -n arr=$1
local tmparr
for (( i = 1; i < ${#arr[@]} - 1; ++i )); do
tmparr+=( "${arr[i]}" "${arr[i]}" )
done
arr=( "${arr[0]}" "${tmparr[@]}" "${arr[-1]}" )
}
The name of the array is passed into the function and the name-reference variable arr is used to access the elements in the array. At the end, the original array is updated to contain the result.
Note that you can't call this function with an array called arr due to the particular name scoping rules used by bash. You may want to rename the arr variable in the function if this is an issue.
Testing:
$ myarr=( 1 2 3 "here we go" )
$ dup_interal_items myarr
$ printf 'Element: %s\n' "${myarr[@]}"
Element: 1
Element: 2
Element: 2
Element: 3
Element: 3
Element: here we go