if条件on迭代循环bash

时间:2016-08-30 09:31:57

标签: bash

我有一个包含以下内容的文件;

864440 17:59:48.143
864440 17:59:48.221
864441 17:59:48.159
864441 17:59:48.221
864442 17:59:48.159
864442 17:59:48.237
864443 17:59:48.174
864444 17:59:48.190
864444 17:59:48.253
864445 17:59:48.206
864445 17:59:48.268
864446 17:59:48.221
864446 17:59:48.284

我正在做一个while循环来读取第一个和第二个值并将它放在如下的变量上;

while read list; do
     jbnum=`echo $list|awk '{print $1}'`
     time=`echo $list|awk '{print $2}'`
done < jobstmp.txt

我想添加一个if条件,如果jbnum等于下一次迭代,它将获得相同作业编号的时间差,如果没有那么什么都不做并转到下一次迭代

感谢所有根据Chris Maes提供的代码回答以下解决方案的人

while read jobnum time
do
    if [[ "$prevjobnum" == "$jobnum" ]]
    then
        ENDTIME=`date +%s.%N -d "$time"`
        STARTTIME=`date +%s.%N -d "$prevtime"`
        DIFF=$(echo $ENDTIME - $STARTTIME | bc | sed 's/0\{1,\}$//')

        echo "$prevjobnum time is $DIFF seconds"
    fi
    # keep variables for next iteration
    prevjobnum=$jobnum
    prevtime=$time
done < jobstmp.txt

5 个答案:

答案 0 :(得分:1)

你无法提前阅读。你将不得不使用一些中间变量;类似的东西(注意你可以立即读取多个变量):

while read jobnum time
do
    if [[ "$prevjobnum" == "$jobnum" ]]
    then
        #do your stuff with the variables $prevjobnum and $prevtime. for example:
        echo "prevjobnum=$prevjobnum , prevtime=$prevtime"
    fi
    # keep variables for next iteration
    prevjobnum=$jobnum
    prevtime=$time
done < jobstmp.txt

这给出了:

prevjobnum=864440 , prevtime=17:59:48.143
prevjobnum=864441 , prevtime=17:59:48.159
prevjobnum=864442 , prevtime=17:59:48.159
prevjobnum=864444 , prevtime=17:59:48.190
prevjobnum=864445 , prevtime=17:59:48.206
prevjobnum=864446 , prevtime=17:59:48.221

答案 1 :(得分:0)

请注意,您的方法可以通过不必解析$list的方式进行改进。使用read var1 var2 var3...按照Read a file line by line assigning the value to a variable

中的说明单独捕捉它们

这样,你可以得到这样的代码:

while IFS= read -r jbnum time; do
    if [ "$prev_jbnum" == "$jbnum" ]; then
         echo "they are equal!"
    fi
    prev_jbnum=$jbnum
done < jobstmp.txt

但是,要将一列与前一列进行比较,您可以更简单的方式使用awk

$ awk '$1==prev {print $0, "equal!"} {prev=$1}' file
864440 17:59:48.221 equal!
864441 17:59:48.221 equal!
864442 17:59:48.237 equal!
864444 17:59:48.253 equal!
864445 17:59:48.268 equal!
864446 17:59:48.284 equal!

要比较第一个字段匹配的时间,您可以使用mktime()之类的内容,只是它不会处理毫秒。

此外,您必须对数据进行一些按摩才能使用此功能:

{
 gsub(/[^0-9]/, " ", $2)                # replace every : and . with spaces
 current_time=mktime("1970 01 01 " $2); # generate a date prepending 1/1/1970
}

答案 2 :(得分:0)

如果您的ID总是6个字符宽,则可以使用uniq过滤具有特定第一个字段值的第一行:

$ echo """864440 17:59:48.143
864440 17:59:48.221
864441 17:59:48.159
864441 17:59:48.221
864442 17:59:48.159
864442 17:59:48.237
864443 17:59:48.174
864444 17:59:48.190
864444 17:59:48.253
864445 17:59:48.206
864445 17:59:48.268
864446 17:59:48.221
864446 17:59:48.284""" | uniq -w 6

864440 17:59:48.143
864441 17:59:48.159
864442 17:59:48.159
864443 17:59:48.174
864444 17:59:48.190
864445 17:59:48.206
864446 17:59:48.221

然后,您可以在输出行上进行迭代,以便只应该通过第一个字段值执行一次操作。

请注意,必须对数据进行排序才能使uniq正常工作。

答案 3 :(得分:0)

我建议你在循环之前先做一次阅读

read line

while read nextLine; do
    jbnum=`echo $line|awk '{print $1}'`
    time=`echo $line|awk '{print $2}'`

    nextjbnum=`echo $nextLine|awk '{print $1}'`
    nexttime=`echo $nextLine|awk '{print $2}'`

    if [jbnum == nextjbum]; then
       DO STUFF ....
    fi

    #Then save the current line before processing the next
    line=nextLine
done

答案 4 :(得分:0)

在包含

的{}内执行计算
  

打印$ 1,“//在此处进行计算”

awk 'idMap[$1]==""{idMap[$1]=$2;print;next;}{print $1,"//do your calculation here"}' <filaname>

此时生成的输出看起来像这样。

864440 17:59:48.143
864440 //do your calculation here
864441 17:59:48.159
864441 //do your calculation here
864442 17:59:48.159
864442 //do your calculation here
864443 17:59:48.174
864444 17:59:48.190
864444 //do your calculation here
864445 17:59:48.206
864445 //do your calculation here
864446 17:59:48.221
864446 //do your calculation here