awk
標簽(空格分隔): shell編程
Awk文本處理
1.進行逐行掃描文件(或流), 從第一行到最后一行
2.尋找匹配的特定模式的行,在行上進行操作
3.如果沒有指定處理動作,則把匹配的行顯示到標準輸出
4.如果沒有指定模式,則所有被操作的行都被處理
awk的語法格式
awk [options] 'commands' filenames
awk [options] -f awk-script-file filenames
選項 options
-F 定義輸入字段分隔符,默認的分隔符, 空格或tab鍵
命令 command
行處理前 行處理 行處理后
BEGIN{} {} END{}
Awk 工作原理
1.awk將文件中的每一行作為輸入, 并將每一行賦給內部變量$0, 以換行符結束
2.awk開始進行字段分解,每個字段存儲在已編號的變量中,從$1開始[默認空格分割]
3.awk默認字段分隔符是由內部FS變量來確定, 可以使用-F修訂
4.awk行處理時使用了print函數打印分割后的字段
5.awk在打印后的字段加上空格,因為3 之間有一個逗號。逗號被映射至OFS內部變量中,稱為輸出字段分隔符, OFS默認為空格.
6.awk輸出之后,將從文件中獲取另一行,并將其存儲在$0中,覆蓋原來的內容,然后將新的字符串分隔成字段并進行處理。該過程將持續到所有行處理完畢.
Awk內部變量
$0保存當前記錄的內容
awk '{print $0}' /etc/passwd
NR記錄輸入總的編號(行號)
awk '{print NR,$0}' /etc/passwd
awk 'NR<=3' /etc/passwd
FNR當前輸入文件的編號(行號)
awk '{print NR,$0}' /etc/passwd /etc/hosts
awk '{print FNR,$0}' /etc/passwd /etc/hosts
NR與FNR
vim info1.txt
001,小明
002,小張
003,小王
vim info2.txt
001,男,25
002,女,21
003,男,20
合并兩個文件,得到如下結果
001,小明,男,25
002,小張,女,21
003,小王,男,20
awk -F "," 'NR==FNR{s[$1]=$0;next}{print s[$1]","$2","$3}' info1.txt info2.txt
join -t ',' -o 1.1 1.2 2.2 2.3 info1.txt info2.txt
NF保存行的最后一列
awk -F ":" '{print NF,$NF}' /etc/passwd /etc/hosts
FS指定字段分割符, 默認是空格
//以冒號作為字段分隔符
awk -F: '/root/{print $1,$3}' /etc/passwd
awk 'BEGIN{FS=":"} {print $1,$3}' /etc/passwd
//以空格冒號tab作為字段分割
awk -F'[ :\t]' '{print $1,$2,$3}' /etc/passwd
OFS指定輸出字段分隔符
//,逗號映射為OFS, 初始情況下OFS變量是空格
awk -F: '/root/{print $1,$2,$3,$4}' /etc/passwd
awk 'BEGIN{FS=":"; OFS="+++"} /^root/{print $1,$2}' /etc/passwd
RS輸入記錄分隔符,默認為換行符[了解]
awk -F: 'BEGIN{RS=" "} {print $0}' /etc/hosts
ORS將文件以空格為分割每一行合并為一行
awk -F: 'BEGIN{ORS=" "} {print $0}' /etc/hosts
print 輸出函數
date|awk '{print $2,"5月份""\n",$NF,"今年"}'
awk -F: '{print "用戶是:" $1 "\t 用戶uid: " $3 "\t 用戶gid:" $4}' /etc/passwd
printf 格式化輸出函數
awk -F: '{printf "%-15s %-10s %-15s\n", $1, $2, $3}' /etc/passwd
%s 字符類型
%d 數值類型
占 15 字符
- 表示左對齊,默認是右對齊
printf 默認不會在行尾自動換行,加\n
FS與RS
vim record.txt
小明
電話:010-10011010
手機:13388888888
小軍
電話:010-10011011
手機:13399999999
將以上文件內容變為如下格式
小明 電話:010-10011010 手機:13388888888
小軍 電話:010-10011011 手機:13399999999
awk 'BEGIN{FS="\n";RS=""}{print $1"\t"$2"\t"$3}' record.txt
Awk模式動作
awk語句都由模式和動作組成。
模式部分決定動作語句何時觸發及觸發事件。
如果省略模式部分,動作將時刻保持執行狀態。模式可以是條件語句或復合語句或正則表達式。
1.正則表達式
//匹配記錄(整行)
awk '/^root/' /etc/passwd
awk '$0 ~ /^root/' /etc/passwd
//匹配字段:匹配操作符(~ !~)
awk '$1~/^root/' /etc/passwd
awk '$NF !~ /bash$/' /etc/passwd
2.比較表達式
比較表達式采用對文本進行比較,只有當條件為真,才執行指定的動作。
比較表達式使用關系運算符,用于比較數字與字符串
關系運算符
運算符 | 含義 | 示例 |
---|---|---|
< | 小于 | x < y |
<= | 小于或等于 | x<=y |
== | 等于 | x==y |
!= | 不等于 | x!=y |
>= | 大于等于 | x>=y |
> | 大于 | x>y |
//uid為0的列出來
awk -F ":" '$3==0' /etc/passwd
//uid小于10的全部列出來
awk -F: '$3 < 10' /etc/passwd
//用戶登陸的shell等于/bin/bash
awk -F: '$7 == "/bin/bash" ' /etc/passwd
//第一列為alice的列出來
awk -F: '$1 == "alice" ' /etc/passwd
//為alice的用戶列出來
awk -F: '$1 ~ /alice/' /etc/passwd
awk -F: '$1 !~ /alice/' /etc/passwd
//磁盤使用率大于多少則,則打印可用的值
df |awk '/\/$/'|awk '$3>1000000 {print $4}'
3.條件表達式
awk -F: '$3>300 {print $0}' /etc/passwd
awk -F: '{if($3>300) print $0}' /etc/passwd
awk -F: '{if($3>5555){print $3} else {print $1}}' /etc/passwd
4.運算表達式
awk -F: '$3 * 10 > 500000' /etc/passwd
awk -F: 'BEGIN{OFS="--"} { if($3*10>50000) {print $1,$3} } END {print "打印ok"}' /etc/passwd
awk '/southem/{print $5 + 10}' file
awk '/southem/{print $5 + 1.5}' file
awk '/southem/{print $8 - 8}' file
awk '/southem/{print $8 / 3 }' file
awk '/southem/{print $8 * 4 }' file
awk '/southem/{print $8 % 2 }' file
5.邏輯操作符和復合模式
&&邏輯與 || 邏輯或 !邏輯非
//匹配用戶名為root并且打印uid小于15的行
awk -F: '$1~/root/ && $3<=15' /etc/passwd
//匹配用戶名為root或uid大于5000
awk -F: '$1~/root/ || $3>=5000' /etc/passwd
awk示例1
awk '/west/' file
awk '/^north/' file
awk '$3 ~ /^north/' file
awk '/^(no|so)/' file
awk '{print $3,$2}' file
awk '{print $3 $2}' file
awk '{print $0}' file
awk '{print "Number of fields: "NF}' file
awk '/northeast/{print $3,$2}' file
awk '/^[ns]/{print $1}' file
awk '$5 ~ /\. [7-9]+/' file
awk '$2 !~ /E/{print $1,$2}' file
awk '$3 ~ /^Joel/{print $3 "is a nice boy."}' file
awk '$8 ~ /[0-9][0-9]$/{print $8}' file
awk '$4 ~ /Chin$/{print "The price is $" $8 "."}' file
awk '/Tj/{print $0}' file
awk -F: '{print "Number of fields: "NF}' /etc/passwd
awk -F"[ :]" '{print NF}' /etc/passwd
awk條件
if
語句格式:
{ if(表達式){語句;語句;... }}
//打印當前管理員用戶名稱
awk -F: '{ if($3==0){print $1 "is adminisitrator"} }' /etc/passwd
//統計系統用戶數量
awk -F: '{ if($3>0 && $3<1000){i++}} END {print i}' /etc/passwd
//統計普通用戶數量
awk -F: '{ if($3>1000){i++}} END {print i}' /etc/passwd
寫出一個shell腳本,把當前目錄下的文本文件number.txt里面數字大于100的求和并輸出,并打印所在行行號及內容,最后還要輸出每一行的總和。
[root@m01 ~]# cat number.txt
100
98
205
303
1
99
66
33
awk '{if($1>100){sum+=$1;print NR,$0}}{i+=$1}END{print sum,i}' number.txt
3 205
4 303
508 905
if...else
語句格式:
{if(表達式){語句;語句;... }else{語句;語句;...}}
awk -F: '{if($3==0){print $1} else {print $7}}' /etc/passwd
awk -F: '{if($3==0) {count++} else{i++} }' /etc/passwd
awk -F: '{if($3==0){count++} else{i++}} END{print " 管理員個數: "count ; print " 系統用戶數: "i}' /etc/passwd
if...else if...else
語句格式:
{if(表達式 1){語句;語句;... }else if(表達式 2){語句;語句;. .. }else{語句;語句;... }}
awk -F: '{ if($3==0){i++} else if($3>0 && $3<1000){j++} else if($3>1000) {k++}} END {print i;print j;print k}' /etc/passwd
awk -F: '{ if($3==0){i++} else if($3>0 && $3<1000){j++} else if($3>1000) {k++}} END {print "管理員個數"i; print "系統用戶個數" j; print "系統用戶個 數" }' /etc/passwd
管理員個數1
系統用戶個數29
系統用戶個數69
switch-case
BEGIN{
a=2;
b=2;
c=3
switch(a){
case 1: print a;break;
case 2: print b;break;
case 3: print c;break;
}
}
awk循環語句
for循環
C格式
for(初值;終值;步長值){語句}
awk 'BEGIN{for(i=1;i<=5;i++){print i} }'
//將每行打印 10 次
awk -F: '{ for(i=1;i<=10;i++) {print $0} }' passwd
列表
for(變量 in 數組){語句}
while循環
awk 'BEGIN{ i=1; while(i<=10){print i; i++} }'
awk -F: '{i=1; while(i<=NF){print $i; i++}}' /etc/passwd
awk -F: '{i=1; while(i<=10) {print $0; i++}}' /etc/passwd
cat a.txt
111 222
333 444 555
666 777 888 999
awk '{i=1;while(i<=NF){print $i;i++}}' a.txt
用awk獲取文件中第三列打到倒數第二列字段
awk.awk
#!/usr/bin/awk
BEGIN{
FS=":"
OFS=":"
}
{
t=$2;
i=2;
while (i<NF-1)
{
$i=$(i+1);
i++;
}
$(NF-1)=t;
print $0;
}
運行
awk -f awk.awk /etc/passwd
do-while
do
{語句}
while(條件)
break
當 break 語句用于 while 或 for 語句時,導致退出程序循環
continue
當 continue 語句用于 while 或 for 語句時,使程序循環移動到下一個迭代
next
能夠導致讀入下一個輸入行,并返回到腳本的頂部。這可以避免對當前輸入行執行其他的操作過程
vim test.txt
web01[192.168.2.100]
httpd ok
tomcat ok
sendmail ok
web02[192.168.2.101]
httpd ok
postfix ok
web03[192.168.2.102]
mysqld ok
httpd ok
轉換為如下格式
web01[192.168.2.100] httpd ok
web01[192.168.2.100] tomcat ok
web01[192.168.2.100] sendmail ok
web02[192.168.2.101] httpd ok
web02[192.168.2.101] postfix ok
web03[192.168.2.102] mysqld ok
web03[192.168.2.102] httpd ok
awk '/^web/{T=$0;next;}{print T"\t"$0;}' test.txt
vim test1.txt
web01[192.168.2.100] httpd ok
web01[192.168.2.100] tomcat ok
web01[192.168.2.100] sendmail ok
web02[192.168.2.101] httpd ok
web02[192.168.2.101] postfix ok
web03[192.168.2.102] mysqld ok
web03[192.168.2.102] httpd ok
轉換為如下格式
web01[192.168.2.100]
httpd ok
tomcat ok
sendmail ok
web02[192.168.2.101]
httpd ok
postfix ok
web03[192.168.2.102]
mysqld ok
httpd ok
awk 't!=$1{t=$1;print $1"\n"$2,$3;next}{print $2,$3}' test1.txt
awk '{if(t!=$1){t=$1;print $1"\n"$2,$3}else{print $2,$3}}' test1.txt
exit
語句使主輸入循環退出并將控制轉移到END,如果END存在的話。如果沒有定義END規則,或在END中應用exit語句,則終止腳本的執行
awk數組
awk -F: '{username[++i]=$1} END{print username[1]}' /etc/passwd
awk -F: '{username[i++]=$1} END{print username[1]}' /etc/passwd
awk -F: '{username[i++]=$1} END{print username[0]}' /etc/passwd
注意:將需要統計的某個字段作為數組的索引,最后對索引進行遍歷
按索引遍歷
awk -F: '{username[x++]=$1} END{for(i in username) {print i,username[i]} }' /etc/passwd
awk -F: '{username[++x]=$1} END{for(i in username) {print i,username[i]} }' /etc/passwd
1.統計/etc/passwd 中各種類型 shell 的數量
awk -F: '{shells[$NF]++} END{ for(i in shells){print i,shells[i]} }' /etc/passwd
2.網站訪問狀態統計
ss -an|awk '/:80/{tcp[$2]++} END {for(i in tcp){print i,tcp[i]}}'
3.統計當前訪問的每個IP的數量
ss -an|awk -F ':' '/:80/{ips[$(NF-1)]++} END {for(i in ips){print i,ips[i]}}'
Awk數組案例
Nginx日志分析,日志格式如下:
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
52.55.21.59 - - [25/Jan/2018:14:55:36 +0800] "GET /feed/ HTTP/1.1" 404 162 "https://www.google.com/" "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; de) Presto/2.9.168 Version/11.52" "-"
1.統計2015年11月22日,當天的PV量
grep "22/Nov/2015" access.log |wc -l
awk '/22\/Nov\/2015/{i++}END{print i}' access.log
//統計15-19點的pv量
awk '$4>="[25/Jan/2018:15:00:00" && $4<="[25/Jan/2018:19:00:00 {print $0}"' access.log |wc -l
2.統計2018年01月25日,一天內訪問最多的10個IP
awk '/25\/Jan\/2018/ {ips[$1]++} END {for(i in ips){ print ips[i],i}}' access.log |sort -rn|head
//統計15-19點訪問次數最多的10個IP
awk '$4>="[25/Jan/2018:15:00:00" && $4<="[25/Jan/2018:19:00:00"' access.log |awk '{ips[$1]++} END {for(i in ips){print ips[i],i}}'|sort -rn|head
3.統計2018年01月25日,訪問大于100次的IP
awk '/25\/Jan\/2018/ {ips[$1]++} END {for(i in ips){if(ips[i]>100){print i,ips[i]}}}' access.log
4.統計2018年01月25日,訪問最多的10個頁面($request top 10)
awk '/25\/Jan\/2018/ {request[$7]++} END {for(i in request){print request[i],i}}' access.log |sort -rn|head
5.統計2018年01月25日,每個URL訪問內容總大小($body_bytes_sent)
awk '/25\/Jan\/2018/ {request[$7]++;size[$7]+=$10} END {for(i in request){print request[i],i,size[i]}}' access.log |sort -rn|head
6.統計2018年01月25日,每個IP訪問狀態碼數量($status)
awk '{ip_code[$1 " " $9]++} END {for(i in ip_code){print ip_code[i],i}}' access.log|sort -rn|head
7.統計2018年01月25日,訪問狀態碼為404及出現的次數($status)
grep "404" log.bjstack.log |wc -l
awk '{if($9=="404") code[$9]++} END {for(i in code){print i,code[i]}}' access.log
8.統計2018年01月25日,15:00-19:00訪問狀態碼是404
awk '$4>="[25/Jan/2018:15:00:00" && $4<="[25/Jan/2018:19:00:00" && $9=="404" {code[$9]++} END {for(i in code){print i,code[i]}}' access.log
awk '$9=="404" {code[$9]++} END {for(i in code){print i,code[i]}}' access.log
9.統計2018年01月25日,各種狀態碼數量
awk '{code[$9]++} END {for(i in code){print i,code[i]}}' access.log
awk 'BEGIN{i=j=k=n=p=0}{if($9>=100 && $9<200) {i++}
else if ($9>=200 && $9<300) {j++}
else if ($9>=300 && $9<400) {k++}
else if ($9>=400 && $9<500) {n++}
else if($9>=500) {p++}}
END{print i,j,k,n,p,i+j+k+n+p}' access.log
awk數組練習
cat a.txt
a 1
b 3
c 2
d 7
b 5
a 3
g 2
f 6
d 9
awk '{str[$1]+=$2}END{for (i in str){print i,str[i]}}' a.txt
a 4
b 8
c 2
d 16
f 6
g 2
awk '{if(str[$1]){str[$1]=str[$1]" "$2}else{str[$1]=str[$1]$2}}END{for (i in str){print i,str[i]}}' a.txt
a 1 3
b 3 5
c 2
d 7 9
f 6
g 2
awk -F '[ ]+' '$7~/(jpg|bmp|png|jpeg|gif)$/{count[$7]++;sum[$7]+=$10}END{for (i in count)print count[i]"次", i,sum[i]}' access.log
三目運算符
迭代是重復反饋過程的活動,其目的通常是為了逼近所需目標或結果。每一次對過程的重復稱為一次“迭代”,而每一次迭代得到的結果會作為下一次迭代的初始值
[root@web03 ~]# cat lessons.txt
634751 預排
568688 預排
386760 刪除
619373 預排
428491 預排
487563 完成
603342 完成
436339 完成
結果:
刪除 386760
完成 487563,603342,436339
預排 634751,568688,619373,428491
awk '{a[$2]=a[$2]" "$1}END{for(i in a) print i,a[i]}' lessons.txt
刪除 386760
完成 487563 603342 436339
預排 634751 568688 619373 428491
awk '{a[$2]=a[$2]","$1}END{for(i in a) print i,a[i]}' lessons.txt
刪除 ,386760
完成 ,487563,603342,436339
預排 ,634751,568688,619373,428491
awk '{a[$2]=a[$2]?a[$2]","$1:a[$2]$1}END{for(i in a) print i,a[i]}' lessons.txt
刪除 386760
完成 487563,603342,436339
預排 634751,568688,619373,428491
awk '{if(a[$2]){a[$2]=a[$2]","$1}else{a[$2]=a[$2]$1}}END{for(i in a) print i,a[i]}' lessons.txt
刪除 386760
完成 487563,603342,436339
預排 634751,568688,619373,428491
awk函數
awk內置函數
gsub
gsub(/正則匹配/,"替換后的內容",字段)
[root@oldboy files]# awk '$2~/^Xiaoyu$/{gsub(/:/,"$",$NF);print $NF}' reg.txt
$155$90$201
[root@m01 ~]# cat test
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
[root@m01 ~]# awk '{gsub("root","wuxing");print > "test"}' test
[root@m01 ~]# cat test
wuxing:x:0:0:wuxing:/wuxing:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/wuxing:/sbin/nologin
substr
substr(某一列,從第幾個字符開始,截取幾個字符結束)
echo abcdefghi |awk '{print substr($1,6,2)}'
fg
每分鐘每個資源的訪問次數最多的10個
awk '{a[substr($4,2,17)" "$7]++}END{for (i in a) print a[i],i}' access.log |sort -rn |head
151 22/Nov/2015:11:37 /online/api/mc/cart/new/getCart.json
117 22/Nov/2015:11:29 /online/api/mc/cart/new/getCart.json
116 22/Nov/2015:11:38 /online/api/mc/cart/new/getCart.json
110 22/Nov/2015:11:38 /online/api/mc/sys/nowTime.json
109 22/Nov/2015:11:34 /online/api/mc/cart/new/getCart.json
108 22/Nov/2015:11:30 /online/api/mc/cart/new/getCart.json
104 22/Nov/2015:12:00 /online/api/mc/sys/nowTime.json
104 22/Nov/2015:11:36 /online/api/mc/cart/new/getCart.json
104 22/Nov/2015:11:27 /online/api/mc/sys/nowTime.json
103 22/Nov/2015:11:30 /online/api/mc/sys/nowTime.json
split
精確切割
split(s, a [, r])
split(某一列,數組名字,/正則表達式/)
把某一列通過正則表達式切割,切完后放到數組中
- 注意:數組元素是從1開始
echo GET /mobile/theme/oldboy/common/images/arrow-down2.png
GET /mobile/theme/oldboy/common/images/arrow-down2.png
echo GET /mobile/theme/oldboy/common/images/arrow-down2.png |awk '{split($2,arr,/\./);print arr[1]}'
/mobile/theme/oldboy/common/images/arrow-down2
echo GET /mobile/theme/oldboy/common/images/arrow-down2.png |awk '{split($2,arr,/\./);print arr[2]}'
png
echo GET /mobile/theme/oldboy/common/images/arrow-down2.png |awk '{split($2,arr,/\./);print arr[1],arr[2]}'
/mobile/theme/oldboy/common/images/arrow-down2 png
echo GET /mobile/theme/oldboy/common/images/arrow-down2.png |awk '{split($2,arr,/\./);for(i in arr) print i}'
1
2
echo GET /mobile/theme/oldboy/common/images/arrow-down2.png |awk '{split($2,arr,/\./);for(i in arr) print i,arr[i]}'
1 /mobile/theme/oldboy/common/images/arrow-down2
2 png
system
awk調用shell命令
awk 'BEGIN{system("ls")}'
awk自定義函數
awkfun.awk
#!/usr/bin/awk
function sum(num1,num2)
{
s=num1+num2;
print s;
}
BEGIN{
sum(1,2)
}
#!/usr/bin/awk
function sum(num1,num2)
{
s=num1+num2;
return s;
}
BEGIN{
res=sum(1,2);
print res;
}
運行awk腳本
awk -f awkfun.awk
awk命令行參數
ARGC是命令行參數數量
ARGV是將命令行參數存到數組,元素由ARGC指定,數組下標從0開始
awk 'BEGIN{print ARGC}' 1 2 3
4
awk 'BEGIN{print ARGV[0]}'
awk
awk 'BEGIN{print ARGV[1]}' 1 2
1
蓄水池問題
某蓄水池有甲,丙兩條進水管和乙,丁兩條排水管,要灌滿一池水,單開甲需要3個小時,單開丙管需要5小時,要排光一池水,單開乙管需要4小時,單開丁管需要6小時,現在池內有1/6池水,如果按照甲乙丙丁的順序,循環開各水管,每次每管開一小時。問多少時間后水池開始溢出水?
shell腳本
#!/bin/bash
s=10
t=0
va=$(printf "%.2f" `echo "scale=2;60/180" |bc`)
vb=$(printf "%.2f" `echo "scale=2;60/240" |bc`)
vc=$(printf "%.2f" `echo "scale=2;60/300" |bc`)
vd=$(printf "%.2f" `echo "scale=2;60/360" |bc`)
while (($(echo "$s<60" |bc)==1));do
if (($(echo "$s<60" |bc)==1));then
for ((i=1;i<=60;i++));do
s=$(printf "%.2f" `echo "scale=2;$s+$va" |bc`)
((t++))
if (($(echo "$s<60" |bc)!=1));then
break
fi
done
fi
if (($(echo "$s<60" |bc)==1));then
s=$(printf "%.2f" `echo "scale=2;$s-$vb*60" |bc`)
((t+=60))
fi
if (($(echo "$s<60" |bc)==1));then
for ((i=1;i<=60;i++));do
s=$(printf "%.2f" `echo "scale=2;$s+$vc" |bc`)
((t++))
if (($(echo "$s<60" |bc)!=1));then
break
fi
done
fi
if (($(echo "$s<60" |bc)==1));then
s=$(printf "%.2f" `echo "scale=2;$s-$vd*60" |bc`)
((t+=60))
fi
done
echo $t
#!/bin/bash
s=10
t=0
va=$(printf "%.2f" `echo "scale=2;60/180" |bc`)
vb=$(printf "%.2f" `echo "scale=2;60/240" |bc`)
vc=$(printf "%.2f" `echo "scale=2;60/300" |bc`)
vd=$(printf "%.2f" `echo "scale=2;60/360" |bc`)
function s_add(){
vx=$1
if (($(echo "$s<60" |bc)==1));then
for ((i=1;i<=60;i++));do
s=$(printf "%.2f" `echo "scale=2;$s+$vx" |bc`)
((t++))
if (($(echo "$s<60" |bc)!=1));then
break
fi
done
fi
}
function s_dec(){
vx=$1
if (($(echo "$s<60" |bc)==1));then
s=$(printf "%.2f" `echo "scale=2;$s-$vx*60" |bc`)
((t+=60))
fi
}
while (($(echo "$s<60" |bc)==1));do
s_add $va
s_dec $vb
s_add $vc
s_dec $vd
done
echo $t
awk腳本
#!/usr/bin/awk
BEGIN{
s=10;
va=60/180;
vb=60/240;
vc=60/300;
vd=60/360;
while(s<60)
{
if(s<60)
{
for(i=1;i<=60;i++)
{
s+=va;
t+=1;
if(s>=60)
{
break;
}
}
}
if(s<60)
{
s-=vb*60;
t+=60;
}
if (s<60)
{
for(i=1;i<=60;i++)
{
s+=vc;
t+=1;
if(s>=60)
{
break;
}
}
}
if(s<60)
{
s-=vd*60;
t+=60;
}
}
print t;
}
執行
awk -f water1.awk
#!/usr/bin/awk
function s_add(vx){
if(s<60)
{
for(i=1;i<=60;i++)
{
s+=vx;
t+=1;
if(s>=60)
{
break;
}
}
}
}
function s_dec(vx){
if(s<60)
{
s-=vx*60;
t+=60;
}
}
BEGIN{
s=10;
va=60/180;
vb=60/240;
vc=60/300;
vd=60/360;
t=0;
while(s<60)
{
s_add(va);
s_dec(vb);
s_add(vc);
s_dec(vd);
}
print t;
}
最終版
#!/usr/bin/awk
BEGIN{
s=1/6;
v["a"]=1/10800;
v["b"]=-1/14400;
v["c"]=1/18000;
v["d"]=-1/21600;
while(s<1)
{
for (i in v)
for(n=1;n<=3600;n++)
if(s<1)
{
s+=v[i];
t+=1;
}
}
print int(t/3600)"小時"int(t%3600/60)"分"t%3600%60"秒"
}