awk

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在打印后的字段加上空格,因為1,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"秒"
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Linux指令中文說明傳送入口 整理自Linux指令中文說明 文本和數據進行處理的編程語言awk 是一種編程語言,...
    釋閑人閱讀 2,145評論 1 6
  • awk介紹awk變量printf命令:實現格式化輸出操作符awk patternawk actionawk數組aw...
    哈嘍別樣閱讀 1,588評論 0 4
  • 轉載 原文的排版和內容都更加友好,并且詳細,我只是在這里貼出了一部分留作自己以后參考和學習,如希望更詳細了解AWK...
    XKirk閱讀 3,254評論 2 25
  • awk: grep,sed,awk grep:文本過濾 sed:文本編輯 awk:文本格式化工具; 1 什么是aw...
    木林森閱讀 1,807評論 0 16
  • 本章主要學習內容awk介紹 ?awk基本用法 ?awk變量 ?awk格式化 ?awk操作符 ?awk條件判斷 ?a...
    楠人幫閱讀 1,286評論 0 8