Você pode diminuir o número de operações e pular a chamada para seq
:
for (( i = 1; i < ${#myarr[@]} - 1; ++i )); do
newarr+=( "${myarr[i]}" "${myarr[i]}" )
done
newarr=( "${myarr[0]}" "${newarr[@]}" "${myarr[-1]}" )
Isso pressupõe que newarr
esteja vazio para começar. Do unset newarry
primeiro, se não for.
Como uma função (isso modifica a matriz que é passada):
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]}" )
}
O nome da matriz é passado para a função e a variável de referência de nome arr
é usada para acessar os elementos na matriz. No final, o array original é atualizado para conter o resultado.
Eu fiz dessa maneira, em vez de retornar uma matriz, pois você só pode retornar um status de saída de uma função. A outra abordagem seria passar os nomes de uma matriz de entrada e uma matriz de saída e usar duas variáveis de referência de nome na função.
Ou, você poderia, possivelmente, echo
ou printf
os valores na função (nesse caso, não é necessário construir um novo array) e, em seguida, analisar esses dados no código principal. A função seria, então, necessária para ser chamada dentro de uma substituição de comando.
Observe que você não pode chamar essa função com uma matriz chamada arr
devido às regras específicas de definição de escopo de nome usadas por bash
. Você pode querer renomear a variável arr
na função se isso for um problema.
Teste:
$ 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
Para duplicar todas as linhas de um arquivo, exceto a primeira e a última linha:
sed -e '1b' -e '$b' -e 'p' <file
O script sed
ramifica para o final (onde há uma instrução de impressão implícita) se estiver na primeira ou na última linha, mas imprime todas as outras linhas (todas as outras linhas são, portanto, explicitamente impressas pela última p
e implicitamente impressos).
Ou, conforme contribuído por don_crissti,
sed 'p;1d;$d' <file
que imprime explicitamente cada linha, termina o ciclo da primeira e última linha, mas imprime implicitamente todas as outras linhas (uma segunda vez).
Um programa equivalente em awk
que não armazena mais do que uma única linha na memória seria não trivial para escrever.