使用数组的Bash函数不起作用

时间:2015-04-05 08:24:13

标签: arrays bash function

我正在尝试在bash中编写一个函数,但它不起作用。该函数如下,它获取格式为:

的文件
1 2 first 3
4 5 second 6
...

我试图只访问每行中第3个字的字符串,并用它们填充数组“arr”,而不重复相同的字符串。 当我在for循环之后立即激活“echo”命令时,它在每次迭代中只打印了第一个字符串(在上面的例子中是“first”)。

谢谢!

function storeDevNames {

n=0
b=0
while read line; do
    line=$line
    tempArr=( $line )
    name=${tempArr[2]}
    for i in $arr ; do
        #echo ${arr[i]}
        if [ "${arr[i]}" == "$name" ]; then
            b=1
            break
        fi
    done
    if [ "$b" -eq 0 ]; then
        arr[n]=$name
        n=$(($n+1))
    fi
    b=0
done < $1
}

3 个答案:

答案 0 :(得分:1)

您可以将所有read块替换为:

arr=( $(awk '{print $3}' <"$1" | sort | uniq) )

这将使arr仅使用第3个字中的唯一名称填充firstsecond,...这会将整个功能缩减为:

function storeDevNames {
    arr=( $(awk '{print $3}' <"$1" | sort | uniq) )
}

注意:这将以排序顺序提供所有唯一设备名称的列表。删除重复项也会破坏原始订单。如果保留订单接受删除重复项的位置,请参阅4ae1e1的替代方案。

答案 1 :(得分:1)

以下行似乎可疑

    for i in $arr ; do

我按照以下方式更改了它,它对我有用:

#! /bin/bash

function storeDevNames {
    n=0
    b=0
    while read line; do
        # line=$line # ?!
        tempArr=( $line )
        name=${tempArr[2]}
        for i in "${arr[@]}" ; do
            if [ "$i" == "$name" ]; then
                b=1
                break
            fi
        done
        if [ "$b" -eq 0 ]; then
            arr[n]=$name
            (( n++ ))
        fi
        b=0
    done
}

storeDevNames < <(cat <<EOF 
1 2 first 3
4 5 second 6
7 8 first 9
10 11 third 12
13 14 second 15
EOF
)

echo "${arr[@]}"

答案 2 :(得分:1)

您使用了错误的工具。 awk专为此类工作而设计。

awk '{ if (!seen[$3]++) print $3 }' <"$1"

这个单行打印每行的第三列,沿途保留重复项,同时保留行的顺序(仅打印每个唯一字符串的第一个出现)。另一方面,sort | uniq打破了原始的行顺序。这个单线程也比使用sort | uniq更快(对于大型文件,这似乎不适用于OP的情况),因为这个单线程扫描文件一次,而sort显然要贵得多。

例如,对于包含内容的输入文件

1 2 first 3
4 5 second 6
7 8 third 9
10 11 second 12
13 14 fourth 15

以上awk单行给你

first
second
third
fourth

将结果放入数组:

arr=( $(awk '{ if (!seen[$3]++) print $3 }' <"$1") )

然后echo ${arr[@]}会给你first second third fourth