[英]Iterating over lines (w/ numbers) read from a file to an array in bash
我正在尝试编写一个小的脚本,该脚本将采用文件的第4列并将其存储在数组中,然后进行一些比较。 如果数组中的元素大于0且小于500,则必须增加计数器。 但是,当我运行脚本时,计数器始终显示0。这是我的脚本
#!/bin/bash
mapfile -t my_array < <(cat file1.txt | awk '{ print $4 }' > test.txt)
COUNTER=0
for i in ${my_array[@]}; do
if [["${my_array[$i]}" -gt 0 -a "${my_array[$i]}" -lt 500 ]]
then
COUNTER=$((COUNTER + 1))
fi
printf "%s\t%s\n" "%i" "${my_array[$i]}"//just to test if the mapfile command is working
done
echo $COUNTER
输出:
./script1.bash
0
#!/bin/bash
mapfile -t my_array < <(awk '{ print $4 }' file1.txt | tee test.txt)
COUNTER=0
for idx in "${!my_array[@]}"; do
value=${my_array[$idx]}
if (( value > 0 )) && (( value < 500 )); then
COUNTER=$((COUNTER + 1))
fi
printf "%s\t%s\n" "$idx" "$value"
done
echo "$COUNTER"
cat
:它只增加了效率,无所作为(需要启动一个额外的过程,并迫使awk从管道读取而不是从文件直接读取)。 awk
的输出已重定向到test.txt
因此mapfile
无需读取任何内容。 如果要同时进入文件和 stdout,则需要使用tee
。 -a
在[[ ]]
无效; 使用&&
代替。 但是,由于仅执行算术运算,因此(( ))
更合适。 顺便说一句, -a
即使[ ]
和test
也被正式标记为过时; 请参阅当前的POSIX标准 。 ${my_array[@]}
遍历value 。 如果要遍历索引 ,则需要${!my_array[@]}
。 [["$foo"
是与[[
不同的命令,除非$foo
为空或以$ IFS中的字符开头。 如果将输出重定向到文件: > test.txt
则“标准输出”中没有输出,因为该文件已使用该输出。 因此,首先,您需要删除该重定向。 您可以使用:
mapfile -t my_array < <(cat file1.txt | awk '{ print $4 }' )
但是由于awk可以很好地读取文件,因此更好:
mapfile -t my_array < <(awk '{ print $4 }' file1.txt)
并且由于您使用的是awk,因此可以将其与0和500进行比较,并输出整个计数。
counter=$(awk '{if($4>0 && $4<500){c++}}END{print c}' file1.txt)
echo "$counter"
更简单,更快。
这样也可以避免脚本中的一些简单错误,例如在[…]
构造中缺少空格:
if [[ "${my … # NOT "if [["${my …"
还有一些遗漏的引号:
for i in "${my_array[@]}" # NOT for i in ${my_array[@]}
通常,最好使用ShellCheck.net检查脚本,以删除一些简单的错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.