bash while循环中的最后一行处理

时间:2016-02-15 18:09:44

标签: bash

我有一个包含以下10个数字的文件:

> cat numbers
9
11
32
88
89
90
95
104
118
120
>

我想打印出前面的数字,只要它比当前数字小至少5个数字。所以我希望输出如下:

11
32
90
95
104
120

我有一个脚本可以执行此操作:

> cat test.sh
#!/bin/bash

subtraction="5"

while read -r number; do

  if [ -n "$previous_number" ] && (( $((number - subtraction)) >= previous_number )); then
    echo "$previous_number"
  fi

  previous_number="$number"

done < "$1"
> ./test.sh numbers 
11
32
90
95
104
> 

但是,它不会打印120。在这种情况下,最优雅/最合适的解决方案是什么?我应该在while循环后添加tail -1 "$1"吗?

2 个答案:

答案 0 :(得分:2)

使用awk来完成这项工作更容易:

awk 'NR>1 && $1-p>=5{print p} {p=$1}' file

<强>输出:

11
32
90
95
104

btw 120不会在输出中打印,因为前面的数字是118,而不是<=5120

答案 1 :(得分:2)

如果其他人在阅读此内容时while read 真的没有迭代文件的最后一行,那么可能存在不同的问题:没有尾随换行符的输入文件

对于那个,可以按如下方式修改其代码:

while read -r number || [[ $number ]]; do
  : "...logic here..."
done

这是正确的,因为如果没有尾随换行符,read将返回false,因此循环体不会使用原始代码执行,但仍会填充$number

然而,对于这个特定的程序及其给出的具体输入,while read成语如何处理输入的最后一行并没有任何错误;手头的输出遵循程序的逻辑编写和定义。

考虑以下版本,这使得发生的事情变得更加清晰:

#!/bin/bash
subtraction="5"
while read -r number; do
  if [[ $previous_number ]] && (( (number - subtraction) >= previous_number )); then
    printf '%q is at least %q away from %q\n' "$previous_number" "$subtraction" "$number"
  else
    printf '%q is not %q away from %q\n' "$previous_number" "$subtraction" "$number"
  fi
  previous_number="$number"
done <"$1"

它的输出是:

'' is not 5 away from 9
9 is not 5 away from 11
11 is at least 5 away from 32
32 is at least 5 away from 88
88 is not 5 away from 89
89 is not 5 away from 90
90 is at least 5 away from 95
95 is at least 5 away from 104
104 is at least 5 away from 118
118 is not 5 away from 120

...正如最后一行输出所示, 正在考虑120,并决定不按照您定义的程序逻辑打印它。