数组的重复元素(第一个和最后一个元素除外)

数组的重复元素(第一个和最后一个元素除外)

我有一个数组,我想重复除第一个和最后一个元素之外的每个元素。

例如,如果数组有五个元素1 2 3 4 5,那么重复之后,它的元素应该是1 2 2 3 3 4 4 5

我的 bash 命令是

$ newarr=("${myarr[0]}")
$ for i in $(seq 1 $((${#myarr[@]}-2))) ; do newarr+=( "${myarr[i]}" "${myarr[i]}"); done
$ newarr+=("${myarr[-1]}")

有比我更清楚的方法吗?

我还想知道如何将其包装到一个以myarr参数为参数并返回的函数中newarr。 (创建这样的函数后,我将从文件中读取一个数组,以便每个元素在文件中存储一行,然后在数组上调用该函数。如果创建这样的函数不是一个好方法,请告诉我.)

谢谢。

答案1

您可以稍微减少操作次数,并跳过对 的调用seq

for (( i = 1; i < ${#myarr[@]} - 1; ++i )); do
    newarr+=( "${myarr[i]}" "${myarr[i]}" )
done
newarr=( "${myarr[0]}" "${newarr[@]}" "${myarr[-1]}" )

这假设newarr一开始就是空的。unset newarry如果没有就先做。

作为函数(这会修改传递的数组):

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]}" )
}

姓名数组的值被传递到函数中,名称引用变量arr用于访问数组中的元素。最后,更新原始数组以包含结果。

我这样做而不是返回一个数组,因为您只能从函数返回退出状态。另一种方法是传递输入数组的两个名称输出数组并在函数中使用两个名称引用变量。

或者,您可以echoprintf函数中的值(在这种情况下您根本不必构造新数组),然后在主代码中解析该数据。然后需要在命令替换内调用该函数。

请注意,您不能arr使用由于 所使用的特定名称范围规则而调用的数组来调用此函数bash。如果这是一个问题,您可能需要重命名arr函数中的变量。

测试:

$ 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

要复制文件中除第一行和最后一行之外的所有行:

sed -e '1b' -e '$b' -e 'p' <file

如果脚本sed位于第一行或最后一行,则脚本分支到末尾(其中存在隐式打印语句),但打印所有其他行(因此所有其他行均由最后一行显式打印p并隐式打印)。

或者,由 don_crissti 贡献,

sed 'p;1d;$d' <file

它显式打印每一行,然后结束第一行和最后一行的循环,但隐式打印所有其他行(第二次)。

一个在内存中不存储多于一行的等效awk程序编写起来并不简单。

答案2

也尝试一下 - 不需要功能 -

$ ARR=(1 2 3 4 5)
$ IFS=$'\n\t '
$ readarray NEWARR < <(echo "${ARR[*]}" | sed '1!p; $d')
$ echo ${NEWARR[@]}
1 2 2 3 3 4 4 5

甚至

NEWARR=($(printf "%s\n" ${ARR[@]} | sed '1!p; $d'))

答案3

接受换行符的解决方案:

#!/bin/bash
arr=( 1 2 "3 3" $'41\n42' 5 )

readarray -t -d $'\0' newarray < <(printf '%s\0' "${arr[@]}" | sed -z '1!p; $d')

printf '<%s>\n' "${newarr[@]}"

运行为:

$ ./script
<1>
<2>
<2>
<3 3>
<3 3>
<41
42>
<41
42>
<5>

相关内容