elecsnail的个人空间 https://bbs.21ic.com/?867354 [收藏] [复制] [RSS]

日志

shell中的数值计算

已有 1287 次阅读2013-3-13 13:27 |系统分类:兴趣爱好| 计算,

#!/bin/bash
echo "please input number:"
read n
a=`expr $n / 100`
#a1=`expr $n - $a * 100`
b=`echo "($n-$a*100)/10" | bc`
c=`echo "($n-$a*100-$b*10)" | bc`

d=`echo "$c*100+$b*10+$a" | bc`
echo $d
转:http://bbs.techrepublic.com.cn/viewthread.php?tid=140425
1.对某个数加一
$ i=0;
$ ((i++))
$ echo $i
1
$ let i++
$ echo $i
2
$ expr $i + 1
3
$ echo $i
2
$ echo $i 1 | awk '{printf $1+$2}'

let i++;
i=$(expr $i + 1)
i=$(echo $i+1|bc)
i=$(echo "$i 1" | awk '{printf $1+$2;}')


2.用time统计脚本运行时间
$ time calc.sh
10000

real    0m1.319s
user    0m1.056s
sys     0m0.036s
$ time calc_let.sh

3.用shell的内置命令查看各个命令的类型如下:
$ type type
type is a shell builtin
$ type let
let is a shell builtin
$ type expr
expr is hashed (/usr/bin/expr)
$ type bc
bc is hashed (/usr/bin/bc)
$ type awk
awk is /usr/bin/awk

4.let,expr,bc都可以用来求模,运算符都是%,而let和bc可以用来求幂,运算符不一样,前者是**,后者是^
//求模
$ expr 5 % 2
1
$ let i=5%2
$ echo $i
1
$ echo 5 % 2 | bc
1
$ ((i=5%2))
$ echo $i
1
//求幂
$ let i=5**2
$ echo $i
25
$ ((i=5**2))
$ echo $i
25
$ echo "5^2" | bc
25

5.浮点预算,
let和expr都无法进行浮点运算,但是bc和awk可以。
例一:
   $ echo "scale=3; 1/13"  | bc
    .076
   $ echo "1 13" | awk '{printf("%0.3f\n",$1/$2)}'
    0.077
例二:
$ echo 1/13100 | bc -l
.00007633587786259541

例三:
假如有这样一组数据,存放有某个村庄所有家庭的人数和月总收入,要求找 出人均月收入最高的家庭。文件名为innode
1 3 4490
2 5 3896
3 4 3112
4 4 4716
5 4 4578
6 6 5399
7 3 5089
8 6 3029
9 4 6195
10 5 5145
注:通过下面脚本产生上面三列随机数:
for i in $(seq 1 10);do echo $i $(($RANDOM/8192+3)) $((RANDOM/10+3000));done

说明:上面的三列数据分别是家庭编号、家庭人数、家庭月总收入。
分析:为了求出月均收入最高的家庭,我们需要对后面两列数进行除法运算,即求出每个家庭的月均收入,然后按照月均收入排序,找出收入最高的家庭。

#!/bin/bash
# gettopfamily.sh
[ $# -lt 1 ] && echo "please input the file who store the income data" && exit -1[ ! -f $1 ] && echo "$1 is not a file" && exit -1income=$1awk '{        printf("%d %0.2f\n", $1, $3/$2);}' $income | sort -k 2 -n -r

6.产生一个随机数
环境变量RANDOM产生0到32767的随机数,而awk的rand函数可以产生0到1之间的随机数。
例一:
$ echo $RANDOM
81
$ echo "" | awk '{srand(); printf("%f", rand());}'
0.237788

说明:srand在无参数时,采用当前时间作为rand随机数产生器的一个seed

7.统计某篇文章中单词出现的个数:
cat text | sed -e "s/[^a-zA-Z]/\n/g" | grep -v ^$ | sort | uniq -c 
8.
统计出出现频率最高的前10个单词
cat text | sed -e "s/[^a-zA-Z]/\n/g" | grep -v ^$ | sort | uniq -c | sort -n -k 1 -r | head -10

说明:
cat text: 显示text文件里的内容
sed -e "s/[^a-zA-Z]/\n/g": 把非字母的字符全部替换成空格,这样整个文本只剩下字母字符
grep -v ^$:去掉空行
sort: 排序
uniq -c:统计相同行的个数,即每个单词的个数
sort -n -k 1 -r:按照第一列(-k 1)的数字(-n)逆序(-r)排序
head -10:取出前十行
9.统计文章里含有的指定单词的数量
代码一
#!/bin/bash
# statistic_words.sh
if [ $# -lt 1 ]; then        
echo "ERROR: you should input 2 words at least";        
echo "Usage: basename $0 FILE WORDS ...."       
exit -1
fi
FILE=$1
((WORDS_NUM=$#-1))
for n in $(seq $WORDS_NUM)
do    
shift    cat $FILE | sed -e "s/[^a-zA-Z]/\n/g" | grep -v ^$ | sort | grep ^$1$ | uniq -c
done
代码二
#!/bin/bash
# statistic_words.sh
if [ $# -lt 1 ]; then        
echo "ERROR: you should input 2 words at least";        
echo "Usage: basename $0 FILE WORDS ...."        
exit -1
fi
FILE=$1
((WORDS_NUM=$#-1))
for n in $(seq $WORDS_NUM)
do    
shift    cat $FILE | sed -e "s/[^a-zA-Z]/\n/g" | grep -v ^$ | sort | uniq -c | grep " $1$"
done

说明:很明显,采用第一种办法效率要高很多,因为第一种办法提前找出了需要统计的单词,然后再统计,而后者则不然。实际上,如果使用grep的-E选项, 我们无须引入循环,而用一条命令就可以搞定:
$ cat text | sed -e "s/[^a-zA-Z]/\n/g" | grep -v ^$ | sort | grep -E "^Action$|^is$" | uniq
-c
或者
$ cat text | sed -e "s/[^a-zA-Z]/\n/g" | grep -v ^$ | sort | egrep  "^Action$|^is$" | uniq
-c

补充:
在《高级Bash脚本编程指南》一书中还提到jot命令和factor命令
factor产生一个数的所有素数


路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)