当前位置:K88软件开发文章中心网站服务器框架Shell → 文章内容

Shell 数值运算

减小字体 增大字体 作者:佚名  来源:网上搜集  发布时间:2019-1-23 14:39:33

数。而 awk 在控制小数位数时非常灵活,仅仅通过 printf 的格式控制就可以实现。补充:在用 bc 进行运算时,如果不用 scale 指定精度,而在 bc 后加上 -l 选项,也可以进行浮点运算,只不过这时的默认精度是 20 位。例如:$ echo 1/13100 | bc -l.00007633587786259541范例:余弦值转角度用 bc -l 计算,可以获得高精度:$ export cos=0.996293; echo "scale=100; a(sqrt(1-$cos^2)/$cos)*180/(a(1)*4)" | bc -l4.9349547554113836327198340369318406051597063986552438753727649177325495504159766011527078286004072131当然也可以用 awk 来计算:$ echo 0.996293 | awk '{ printf("%s\n", atan2(sqrt(1-$1^2),$1)*180/3.1415926535);}'4.93495范例:有一组数据,求人均月收入最高家庭在这里随机产生了一组测试数据,文件名为 income.txt。1 3 44902 5 38963 4 31124 4 47165 4 45786 6 53997 3 50898 6 30299 4 619510 5 5145说明:上面的三列数据分别是家庭编号、家庭人数、家庭月总收入。分析:为了求月均收入最高家庭,需要对后面两列数进行除法运算,即求出每个家庭的月均收入,然后按照月均收入排序,找出收入最高家庭。实现:#!/bin/bash# gettopfamily.sh[ $# -lt 1 ] && echo "please input the income file" && exit -1[ ! -f $1 ] && echo "$1 is not a file" && exit -1income=$1awk '{ printf("%d %0.2fn", $1, $3/$2);}' $income | sort -k 2 -n -r说明:[ $# -lt 1 ]:要求至少输入一个参数,$# 是 Shell 中传入参数的个数[ ! -f $1 ]:要求输入参数是一个文件,-f 的用法见 test 命令,man testincome=$1:把输入参数赋给 income 变量,再作为 awk 的参数,即需处理的文件awk:用文件第三列除以第二列,求出月均收入,考虑到精确性,保留了两位精度sort -k 2 -n -r:这里对结果的 awk 结果的第二列 -k 2,即月均收入进行排序,按照数字排序 -n,并按照递减的顺序排序 -r。演示:$ ./gettopfamily.sh income.txt7 1696.339 1548.751 1496.674 1179.005 1144.5010 1029.006 899.832 779.203 778.008 504.83补充:之前的 income.txt 数据是随机产生的。在做一些实验时,往往需要随机产生一些数据,在下一小节,我们将详细介绍它。这里是产生 income.txt 数据的脚本:#!/bin/bash# genrandomdata.shfor i in $(seq 1 10)do echo $i $(($RANDOM/8192+3)) $((RANDOM/10+3000))done说明:上述脚本中还用到seq命令产生从1到10的一列数,这个命令的详细用法在该篇最后一节也会进一步介绍。随机数环境变量 RANDOM 产生从 0 到 32767 的随机数,而 awk 的 rand() 函数可以产生 0 到 1 之间的随机数。范例:获取一个随机数$ echo $RANDOM81$ echo "" | awk '{srand(); printf("%f", rand());}'0.237788说明: srand() 在无参数时,采用当前时间作为 rand() 随机数产生器的一个 seed 。范例:随机产生一个从 0 到 255 之间的数字可以通过 RANDOM 变量的缩放和 awk 中 rand() 的放大来实现。$ expr $RANDOM / 128$ echo "" | awk '{srand(); printf("%d\n", rand()*255);}'思考:如果要随机产生某个 IP 段的 IP 地址,该如何做呢?看例子:友善地获取一个可用的 IP 地址。#!/bin/bash# getip.sh -- get an usable ipaddress automatically# author: falcon <zhangjinw@gmail.com># update: Tue Oct 30 23:46:17 CST 2007# set your own network, default gateway, and the time out of "ping" commandnet="192.168.1"default_gateway="192.168.1.1"over_time=2# check the current ipaddressping -c 1 $default_gateway -W $over_time[ $? -eq 0 ] && echo "the current ipaddress is okey!" && exit -1;while :; do # clear the current configuration ifconfig eth0 down # configure the ip address of the eth0 ifconfig eth0 \ $net.$(($RANDOM /130 +2)) \ up # configure the default gateway route add default gw $default_gateway # check the new configuration ping -c 1 $default_gateway -W $over_time # if work, finish [ $? -eq 0 ] && breakdone说明:如果你的默认网关地址不是 192.168.1.1,请自行配置 default_gateway(可以用 route -n 命令查看),因为用 ifconfig 配置地址时不能配置为网关地址,否则你的IP地址将和网关一样,导致整个网络不能正常工作。其他运算其实通过一个循环就可以产生一系列数,但是有相关工具为什么不用呢!seq 就是这么一个小工具,它可以产生一系列数,你可以指定数的递增间隔,也可以指定相邻两个数之间的分割符。范例:获取一系列数$ seq 512345$ seq 1 512345$ seq 1 2 5135$ seq -s: 1 2 51:3:5$ seq 1 2 14135791113$ seq -w 1 2 1401030507091113$ seq -s: -w 1 2 1401:03:05:07:09:11:13$ seq -f "0x%g" 1 50x10x20x30x40x5一个比较典型的使用 seq 的例子,构造一些特定格式的链接,然后用 wget 下载这些内容:$ for i in `seq -f"http://thns.tsinghua.edu.cn/thnsebooks/ebook73/%02g.pdf" 1 21`;do wget -c $i; done或者$ for i in `seq -w 1 21`;do wget -c "http://thns.tsinghua.edu.cn/thnsebooks/ebook73/$i"; done补充:在 Bash 版本 3 以上,在 for 循环的 in 后面,可以直接通过 {1..5} 更简洁地产生自 1 到 5 的数字(注意,1 和 5 之间只有两个点),例如:$ for i in {1..5}; do echo -n "$i "; done1 2 3 4 5范例:统计字符串中各单词出现次数我们先给单词一个定义:由字母组成的单个或者多个字符系列。首先,统计每个单词出现的次数:$ wget -c http://tinylab.org$ cat index.html | sed -e "s/[^a-zA-Z]/\n/g" | grep -v ^$ | sort | uniq -c接着,统计出现频率最高的前10个单词:$ wget -c http://tinylab.org$ cat index.html | sed -e "s/[^a-zA-Z]/\n/g" | grep -v ^$ | sort | uniq -c | sort -n -k 1 -r | head -10 524 a 238 tag 205 href 201 class 193 http 189 org 175 tinylab 174 www 146 div 128 title说明:cat index.html: 输出 index.html 文件里的内容sed -e "s/[^a-zA-Z]/\n/g": 把非字母字符替换成空格,只保留字母字符grep -v ^$: 去掉空行so

上一页  [1] [2] [3]  下一页


Shell 数值运算