我正在尝试在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
}
答案 0 :(得分:1)
您可以将所有read
块替换为:
arr=( $(awk '{print $3}' <"$1" | sort | uniq) )
这将使arr
仅使用第3个字中的唯一名称填充first
,second
,...这会将整个功能缩减为:
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
。