总结一个文本文件中的列 - bash

时间:2013-10-30 09:25:06

标签: bash

文本文件

student.txt

jane,good,3
bob,bad,2.6
annie,good,2.8
dan,bad,2

首先我试图打印所有成功的好学生

#!/bin/bash

while IFS=, read -r -a array; do
   [[  "${array[1]}" == "good"  ]] || continue
   printf "%s \n" "${array[0]}" is a ${array[1]} student"
   done  <  "student.txt"

输出

jane is a good student
annie is a good student

接下来我还要在打印学生类型后总结文本文件中第三列的所有数字并且不成功

#!/bin/bash
while IFS=, read -r -a array; do
   [[  "${array[1]}" == "good"  ]] || continue
   printf "%s \n" "${array[0]}" is a ${array[1]} student"

   for n in "${array[2]}"; do
      total=$( "$total +=$n" | bc )
      echo $total
   done
done  <  "student.txt"

输出

jane is a good student
+=3: command not found
annie is a good student
+=2.8: command not found

预期产出

jane is a good student
annie is a good student
total = 5.8

由于我不熟悉bash脚本,我需要向你们寻求帮助。

哦,另外一件事,我似乎无法善用awk实用程序。

即使我尝试使用awk的简单声明 e.g

awk -F","  "{print $1}"  "student.txt"

右边,如果我没有错,它应该返回这样的东西

输出

good
bad
good
bad

但它返回了文本文件的整个值,我不明白为什么

我输出的awk -F“,”“{print $ 1}”“student.txt”

jane,good,3
bob,bad,2.6
annie,good,2.8
dan,bad,2

所以我猜任何建议都使用awk方法。

3 个答案:

答案 0 :(得分:3)

试试这个单行:

awk -F, '$2=="good"{print $1" is good";s+=$3}END{print "total:"s}' file

输出:

jane is good
annie is good
total:5.8

答案 1 :(得分:0)

这应该(不awk):

#!/bin/bash
total=0
while IFS=, read -r -a array; do
    [[  "${array[1]}" == "good"  ]] || continue
    printf "%s is a %s student\n" "${array[@]:0:2}"
    total=$(bc <<< "$total+${array[2]}")
done < "student.txt"
echo "$total"

现在,每个学生都会bc分叉。相反,你可以滥用IFS:

#!/bin/bash
total=()
while IFS=, read -r -a array; do
    [[  "${array[1]}" == "good"  ]] || continue
    printf "%s is a %s student\n" "${array[@]:0:2}"
    total+=( "${array[2]}" )
done < "student.txt"
# Abusing IFS, I know what I'm doing!
IFS="+" bc <<< "${total[*]}"

:)

或者,没有IFS滥用,也没有将数据保存在数据库的内存中:

#!/bin/bash
{
    while IFS=, read -r -a array; do
        [[  "${array[1]}" == "good"  ]] || continue
        printf >&2 "%s is a %s student\n" "${array[@]:0:2}"
        printf "%s+" "${array[2]}"
    done < "student.txt"
    echo "0"
} | bc

备注。在最后一种情况下,我们必须人为添加0。

锻炼。使用dc代替bc

答案 2 :(得分:0)

Pure Bash。遗漏的浮点运算是模拟的。

total=0
while IFS=, read -r -a array
do
  [[  "${array[1]}" == "good"  ]] || continue
  printf "%s \n" "${array[0]} is a ${array[1]} student"

  [[ "${array[2]}" =~ ([0-9])(\.([0-9]))? ]]
  (( total += 10*${BASH_REMATCH[1]} + ${BASH_REMATCH[3]:-0} ))
done  <  "student.txt"

printf "total = %d.%d" $((total/10)) $((total%10)

输出

jane is a good student 
annie is a good student 
total = 5.8