从一个文件读取一个文件到一个数组在bash中的迭代

问题描述:

我想写一个小的脚本,将采取文件的第4列并将其存储在一个数组中,然后做一个比较。如果数组中的元素大于0且小于500,我必须增加计数器。然而,当我运行该脚本计数器始终显示为0。这里是我的脚本从一个文件读取一个文件到一个数组在bash中的迭代

#!/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 
+0

''[''后面需要空格。另外,因为'awk'输出将转到'test.txt',所以你可能不会在'my_array'中得到任何东西。 – codeforester

+0

双引号数组下标,'因为我在“$ {my_array [@]}”;' – Inian

+3

请通过http://shellcheck.net/运行代码,并修复它发问这里之前耳目一新的习惯。 –

#!/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从管道中读取而不是直接从文件中读取)。
  • mapfile没有什么可读的,因为awk的输出被重定向到test.txt。如果你想把它同时转到文件 stdout,那么你需要使用tee
  • -a[[ ]]中无效;改为使用&&。但是,由于您只做算术,所以(())更合适。顺便提一下,即使对于[ ]test-a也被正式标记为过时;见the current POSIX standard
  • ${my_array[@]}重复。如果您要遍历索引,则需要改为${!my_array[@]}
  • 空格在分隔命令名称时是必需的。 [["$foo"是与[[不同的命令,除非$foo为空或以$ IFS中的字符开头。
+0

如果不需要'test.txt',那么mapfile可以写成mapfile -t my_array codeforester

+0

令人惊讶的是'shellcheck'没有捕获到'-a在[[]]'部分无效。应该抓住它! – Inian

+2

@Inian是的,抓到它,但前提是其他的一些问题是固定的,看到https://github.com/koalaman/shellcheck/wiki/SC2108 –

如果您将输出重定向到一个文件:> 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删除一些简单的错误。

+1

支持这一点可以全部在awk的一行中完成。 –