繁体   English   中英

从文件读取的行(带数字)遍历bash中的数组

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM