我正在尝试读取中逐行包含数字的文本文件
test.txt
10.5
0.52
78.5
29.8
45
13
21.45
0.02
0.99
1.00
我想一个接一个地读这个数字,并将它与30进行比较。我不知道该怎么做。
我试过了,但不起作用。
#!/bin/bash
file=~/test.txt
while IFS= read -r line
do
echo $line
if [[ "$line > 30" | bc) -eq "1" ]]; then
echo Greater
else
echo Smaller
fi
done < $file
请注意:我是编程的新手
shell是一种创建/销毁文件、处理和顺序调用其他工具的工具。shell可用于操作文本的强制性POSIX工具(正如您正在尝试的那样(是错误的。因此,在shell中做你想做的事情的正确方法是调用awk,让awk来做剩下的事情:
$ awk '{print $1, ($1 > 30 ? "Greater" : "Smaller")}' test.txt
10.5 Smaller
0.52 Smaller
78.5 Greater
29.8 Smaller
45 Greater
13 Smaller
21.45 Smaller
0.02 Smaller
0.99 Smaller
1.00 Smaller
我只是从你的代码中复制了逻辑,但当然";较小的";应该是";小于或等于";。
阅读why-is-using-a-shell-loop-to-process-text-consided-bad-practice,了解为什么不编写shell循环来操作文本这一非常重要的教训。
此行:
if [[ "$line > 30" | bc) -eq "1" ]]; then
应该是:
if [[ $(echo "$line > 30" | bc) -eq "1" ]]; then
使用unix工具的管道可能会快得多(尤其是因为它只调用bc
一次(
cmp=30
paste test.txt <(sed "s/$/ > $cmp/" test.txt | bc)
| awk '{$2 = ($2 == 0) ? "Smaller" : "Greater"; print}'
| column -t
10.5 Smaller
0.52 Smaller
78.5 Greater
29.8 Smaller
45 Greater
13 Smaller
21.45 Smaller
0.02 Smaller
0.99 Smaller
1.00 Smaller
您可以向bc
提供多个表达式,它将每行返回一个答案。
如果你使用另一个shell(zsh或ksh(,你不需要任何外部工具:
while IFS= read -r num; do
printf '%st' "$num"
(( num > 30 )) && print Greater || print Smaller
done < test.txt
在变量和字段前面添加一元"+"
总是更安全的,以确保必须用数字进行比较,不留任何机会或实现特性
(与x + 0
相同,但不太详细;+ x
是由于额外的空间导致的语法错误(:
{m,g}awk '$++NF = +__ < +$_ ? " >" : "<="' OFS='t' __=30