Bash脚本 - 如何遍历CSV文件中的行

时间:2017-05-04 09:56:55

标签: bash shell loops csv if-statement

我正在使用包含单个列的巨大CSV文件(filename.csv)。从第1列开始,我想读取当前行并将其与前一行的值进行比较。如果是greater OR equal,继续比较,如果当前单元格的值是smaller而不是前一行,则将当前单元格的值除以前一单元格的值并通过打印分部的值退出。例如,从以下示例中:我希望我的bash脚本将327除以340并将0.961765打印到控制台并退出。

338
338
339
340
327
301
299
284
284
283
283
283
282
282
282
283

我用下面的awk尝试了它,它完全正常。

awk '$1 < val {print $1/val; exit} {val=$1}' filename.csv

但是,由于我想要包含大约7个条件语句(if-else&#39; s),我想用更简洁的bash脚本来做这个,这是我的方法。我不习惯说实话,这就是为什么我更喜欢使用bash。

#!/bin/bash

FileName="filename.csv"
# Test when to stop looping
STOP=1

# to find the number of columns
NumCol=`sed 's/[^,]//g' $FileName | wc -c`; let "NumCol+=1"

# Loop until the current cell is less than the count+1

while [ "$STOP" -lt "$NumCol" ]; do

        cat $FileName | cut -d, -f$STOP
        let "STOP+=1"
done

我们如何遍历值并添加条件语句?

PS:我的if-else语句的标准是(如果值($1/val)>&gt; = 0.85且&lt; = 0.9,则打印A,否则如果值($1/val)是> = 0.7且&lt; = 0.8,打印B,如果值($1/val)>> 0.5且&lt; = 0.6打印C,否则打印D)。

2 个答案:

答案 0 :(得分:2)

这是使用switch的GNU awk中的一个,因为我暂时没有使用它:

awk '
$1<p { 
    s=sprintf("%.1f",$1/p)
    switch(s) {
    case "0.9":            # if comparing to values ranged [0.9-1.0[ use /0.9/
        print "A"          # ... in which case (no pun) you don't need sprintf
        break
    case "0.8":
        print "B"
        break
    case "0.7":
        print "c"
        break
    default:
        print "D"
    }
    exit
}
{ p=$1 }' file
D

使用if的其他问题:

awk '
$1<p { 
#    s=sprintf("%.1f",$1/p)  # s is not rounded anymore
    s=$1/p                  
#    if(s==0.9)              # if you want rounding, 
#        print "A"           # uncomment and edit all ifs to resemble
    if(s~/0.9/) 
        print "A"
    else if(s~/0.8/) 
        print "B"
    else if(s~/0.7/) 
        print "c"
    else
        print "D"
    exit
}
{ p=$1 }' file
D

答案 1 :(得分:2)

这是一种替代方法,基于先前的输入数据,描述$1/val与固定数字0.90.70.6的比较。
此解决方案不适用于($1/val) >=0.85 and <=0.9之类的范围,稍后会澄清。

awk 'BEGIN{crit[0.9]="A";crit[0.7]="B";crit[0.6]="C"} \
$1 < val{ss=substr($1/val,1,3);if(ss in crit) {print crit[ss]} else {print D};exit}{val=$1}' file
A

此技术基于检查舍入值$1/val是否属于加载了相应消息的预定义数组。

让我扩展代码以便更好地理解:

awk 'BEGIN{crit[0.9]="A";crit[0.7]="B";crit[0.6]="C"} \   #Define the criteria array. Your criteria values are used as keys and values are the messages you want to print.
$1 < val{
         ss=substr($1/val,1,3);          #gets the first three chars of the result $1/val
         if(ss in crit) {                #checks if the first three chars is a key of the array crit declared in begin
                         print crit[ss]  #if it is, print it's value
                        } 
          else {
                print D                  #If it is not, print D
                };
          exit
        }
{val=$1}' file

使用substr我们得到结果$1/val的前三个字符:
$1/val = 0.961765使用substr($1/val,1,3)返回0.9

如果您想根据0.96等两位小数进行比较,请更改substr($1/val,1,4)之类的子标题。
在这种情况下,您需要在crit数组中提供正确的比较条目,即crit[0.96]="A"