【awk】1-awk基础篇(又名UNIX.She…
2014-05-08 09:38
204 查看
转自:http://bkeep.blog.163.com/blog/static/1234142902010425110453/
导读:[/b]
1,awk基本语法
2,比较操作符
3,复合表达式
4,next命令
5,变量及变量赋值
6,awk中的赋值操作符
7,BEGIN和END
8,内置变量
9,awk使用shell变量
10,awk中的三种流控制语句
10.1 if语句
10.2 while语句:
10.3 for语句:
11,实验:
12,shell里的特殊变量
正文:[/b]
script
由下面的结构组成 /pattern/{actions}
例子:打印fruit_prices.txt文件的内容
[root@master
bkeep]# awk '{print;}' fruit_prices.txt
fruit
price/lbs
quantity
banana
$0.89
100
peach
$0.79
65
kiwi
$1.50
22
pineapple
$1.29
35
apple
$0.99
78
TIPS:[/b]留意printf[/b]的用法
[/b]如果加“-[/b]”说明是左对齐![/b]
[root@master
bkeep]# awk '{printf "%-15s[/b] %s\n", $1, $3;}'
fruit_prices.txt
fruit
quantity
banana
100
peach
65
kiwi
22
pineapple
35
apple
78
留意printf[/b]的用法
[/b]如果不加“-[/b]”说明是右对齐![/b]
[root@master
bkeep]# awk '{printf "s[/b] %s\n", $1, $3;}'
fruit_prices.txt
fruit quantity
banana 100
peach 65
kiwi 22
pineapple 35
apple 78
例子:给价格高于1美元的水果加个星号
[root@master
bkeep]# cat fruit_prices.txt
fruit
price/lbs
quantity
banana
$0.89
100
peach
$0.79
65
kiwi
$1.50
22
pineapple
$1.29
35
apple
$0.99
78
[root@master
bkeep]# cat price.sh
#!/bin/bash
awk '
/
*\$[1-9][0-9]*\.[0-9][0-9] */ {print $1,$2,$3,"*";} //[/b]星号前面一定要留空格,否则匹配不到[/b]
/
*\$0\.[0-9][0-9] */ {print;}
//[/b]以后养成习惯,/ key /[/b]斜杠和key[/b]之间始终留空格[/b]
'
fruit_prices.txt
执行结果:
[root@master
bkeep]# ./price.sh
banana
$0.89
100
peach
$0.79
65
kiwi $1.50 22
*
pineapple $1.29 35
*
apple
$0.99
78
上面的格式很不好看,我们改改它吧!
TIPS[/b]:[/b]$0[/b]:[/b]awk[/b]使用变量[/b]0[/b]原原本本地存储它所读入的整个输入行。这样可以保持和原来文本格式相同的输出[/b]
[root@master
bkeep]# cat price.sh
#!/bin/bash
awk '
/
*\$[1-9][0-9]*\.[0-9][0-9] */ {print $0[/b],"*";}
/
*\$0\.[0-9][0-9] */ {print;}
'
fruit_prices.txt
[root@master
bkeep]# ./price.sh
banana
$0.89
100
peach
$0.79
65
kiwi
$1.50
22 *
pineapple
$1.29
35 *
apple
$0.99
78
{actions;}
expression[/b]
可以使用以下操作符构成[/b]
< [/b]
小于[/b]
> [/b]
大于[/b]
<= [/b]
小于等于[/b]
>= [/b]
大于等于[/b]
== [/b]
等于[/b]
!= [/b]
不等于[/b]
value ~ /pattern/ [/b]
若value[/b]匹配pattern[/b]则为真[/b]
value !~ /pattern/ [/b]
若value[/b]不匹配pattern[/b]则为真[/b]
说明:$2 ~ /^\$[1-9][0-9]* [/b]
将匹配第二列以$[/b]开头,然后大于1[/b]的二位数。(注意,这里是1[/b]而不是10[/b])[/b]
例子:给数量大于50的水果加星号
[root@master
bkeep]# cat larger.sh
#!/bin/bash
awk '
$3>50[/b]
{printf "%s\t%s\n",
$0,"*"}[/b]
$3<=50 {printf "%s\n",$0}
'
fruit_prices.txt
[root@master
bkeep]# ./larger.sh
fruit
price/lbs
quantity
*[/b]
banana
$0.89
100
*
peach
$0.79
65
*
kiwi
$1.50
22
pineapple
$1.29
35
apple
$0.99
78
*
expression)
(expr1)&&
(expr2)
-------
与
(expr1)|| (expr2) -------
或
说明一下:符合表达式必须用括号括起来[/b]
当使用&&[/b]时,expr1[/b]和expr2[/b]必须同时为零(零代表真!呵呵~),复合表达式才为真;[/b]
当使用 ||[/b]
时,expr1[/b]和expr2[/b]
只要有一个为真,复合表达式则为真![/b]
例子:显示价格高于1美元且数量少于50的水果记录,给打个标记!
[root@master
bkeep]# cat larger.sh
#!/bin/bash
awk '
($2 ~
/^\$[1-9][0-9]*\.[/b][0-9][0-9]$/)
&& ($3<50)
{
//这是一个模式匹配(请参阅比较操作符
printf
"%s\t%s\t%s\n", $0,"*","reorder";
}
'
fruit_prices.txt
[root@master
bkeep]# ./larger.sh
kiwi
$1.50
22
*
reorder
pineapple
$1.29
35
*
reorder
例子:给库存少于50的水果价格标签!
[root@master
bkeep]# cat next.sh
#!/bin/bash
awk '
$3
<= 50 { printf "%s\t%s\n",$0,"REORDER" ;
}
$3
> 50 {print $0; }
'
fruit_prices.txt
当输入行为:kiwi
$1.50
22
脚本执行以下过程:
1)检查是否第三列的值22小于50,由于值小于50,执行脚本的第二步
2)打印该行,并在行尾添加REORDER标志
3)检查是否第三列的值22大于50,由于值不大于50,脚本读下一行
呵呵,傻子都看得出这种情况下执行第三步是多余的。那么如何跳过呢?可以使用next命令。
next[/b]命令:告诉awk[/b]跳过剩下的所有模式和表达式,并读取输入的下一行,同时从第一个模式或表达式开始处理该行![/b]
修改后的脚本,加入了next[/b]命令![/b]
[root@master
bkeep]# cat next.sh
#!/bin/bash
awk '
$3
<= 50 { printf "%s\t%s\n",$0,"REORDER" ;next;[/b] }
$3
> 50 {print $0; }
'
fruit_prices.txt
[root@master
bkeep]# ./next.sh
fruit
price/lbs
quantity
banana
$0.89
100
peach
$0.79
65
kiwi
$1.50
22
REORDER
pineapple
$1.29
35
REORDER
apple
$0.99
78
现在脚本执行如下;
1)检查是否第三列的值22小于50,由于值小于50,所以执行脚本第二步
2)打印输出行并在该行后打印REORDER标志(有了[/b]next[/b]后就不再执行$3 > 50 {print $0;
}[/b])
3)读取下一输入行并从第一种模式开始
fruit=100
//把数字赋给fruit变量
fruit=”peach” //把字符串赋给fruit变量
fruit=$1
//把第一列赋给fruit变量
awk[/b]中的数字操作符:[/b]
+ [/b]
加[/b]
- [/b]
减[/b]
* [/b]
乘[/b]
/ [/b]
除[/b]
% [/b]
求余[/b]
^ [/b]
求幂[/b]
应用例子:统计文件中的空行数
[root@master
bkeep]# cat for.sh
#!/bin/bash
for i in
$@;
//这里我们不知道有多少个文件需要统计,所以用$@来接收参数!
do
if
[ -f $i ]; then
echo $i
awk ' /^$/ { x=x+1;} END{print x;}' $i
else
echo "ERROR:$i not a file."
>&2
fi
done
[root@master
bkeep]# ./for.sh aa bb
aa
//文件名为aa
7
//空行数7
bb
//文件名为bb
4
//空行数为4
x+=1
就是x=x+1
-=
x-=1
就是x=x-1
*=
x*=1
就是x=x*1
/=
x/=1
就是x=x/1
%=
x%=2
就是x=x%2
^=
x^=2
就是x=x^2
pattern:模式
这里pattern有两个特殊模式BEGIN和END
下面是BEGIN
END的语法:
awk ‘
BEGIN { actions
}
/ pattern / {
actions }
/ pattern / {
actions }
END { actions
}
‘ files
BEGIN和END都是可选的
·当指定BEGIN模式时,awk在读取任何输入前执行动作
actions
·当指定END模式时,awk在其退出前执行动作actions
这里要特别注意:比如awk读入aa.txt。那么BEGIN只在读入aa时执行一次,然后按行处理的时候不再执行BEGIN指定的action!(也可以这么理解:BEGIN只对文件生效,而不是按行生效!!);理解了BEGIN,END还会糊涂吗?呵呵!
NR[/b]
已经读取过的记录数。[/b]
FNR[/b]
从当前文件中读出的记录数。[/b]
FILENAME[/b]
输入文件的名字。[/b]
FS[/b]
字段分隔符(缺省为空格)。[/b]
RS[/b]
记录分隔符(缺省为换行)。[/b]
OFMT[/b]
数字的输出格式(缺省为[/b]% g[/b])。[/b]
OFS[/b]
输出字段分隔符。[/b]
ORS[/b]
输出记录分隔符。[/b]
NF[/b]
当前记录中的字段数。[/b]
如果你只处理一个文件,则NR
和FNR
的值是一样的。但如果是多个文件, NR是对所有的文件来说的,而FNR
则只是针对当前文件而言。
例子:统计空行的脚本:[/b]
[root@master
bkeep]# cat for.sh
#!/bin/bash
for i in
$@;
do
if
[ -f $i ]; then
#
echo $i
awk 'BEGIN { printf "%s\t",FILENAME;} //输出文件名
/^$/ { x+=1;}
//统计空行
END{avg=100*(x/NR); printf "%s\t%3.1f\n",x,avg;}' $i //最后算百分比及打印结果
else
echo "ERROR:$i not a file."
>&2
fi
done
[root@master
bkeep]# ./for.sh aa bb //显示出来的结果很漂亮。可惜了,文件名没出来!
7
87.5
//怀疑FILENAME内置变量被修改了???
4
57.1
实现,而awk中的变量直接使用xxx来引用。所以我们就要思考如何让awk使用shell变量
语法:[/b]
awk ‘script’
awkvar1=value awkvar2=value
......
files[/b]
说明: awk[/b]:[/b]
命令;[/b]
‘script[/b]’:awk[/b]将要执行的脚本;
awkvarN[/b]:awk[/b]的变量;value[/b]:shell[/b]中的变量值;
files[/b]:将要处理的文件名[/b]
【重点实验—[/b]记忆】[/b]
例子:根据用户提供的水果数量,将低于这个值的水果打印出来!
[root@master
bkeep]# cat awk_var.sh
#!/bin/bash
NUM_FRUIT="$1"
//将用户输入传递给shell变量NUM_FRUIT
if [ -z
"$NUM_FRUIT" ]; then NUM_FRUIT=75;fi //如果用户没有输入,则赋默认值75
awk '
$3 <= num_fruit {print;}
//最终将用户输入传递给awk变量num_fruit
' num_fruit="$NUM_FRUIT"[/b]
fruit_prices.txt
//通过此方法将$NUM_FRUIT
//赋值给num_fruit;即把shell变量赋给awk
执行结果:[/b]
[root@master
bkeep]# ./awk_var.sh 40
//将数量低于40的水果打印出来
kiwi
$1.50
22
pineapple
$1.29
35
[root@master
bkeep]# ./awk_var.sh 30
//将数量低于30的水果打印出来
kiwi
$1.50
22
while语句
for语句
{action1}
else if (expression2)
{action2}
else { action3}
执行过程:[/b]
1)计算expression1的值
2)若expression1为真,执行action1并推出if语句
3)若expression1为假,计算expression2
4)若expression2为真,执行action2并退出if语句
5)若expression2为假,执行action3并退出if
举例:若水果价格高于1美元,那么给它加星号;若水果数量少于50,则给它加REORDER
[root@master
bkeep]# cat reorder.sh
#!/bin/bash
awk '{
printf "%s\t",$0;
if
( $2 ~ /\$[1-9][0-9]*\.[0-9][0-9]/ ) {
printf " * ";
if ($3 <= 75) {
printf "REORDER\n";
} else {
printf "\n";
}
}else {
if ($3<=75) {
printf "REORDER\n";
}else {
printf "\n";
}
}
}'
fruit_prices.txt
执行结果:[/b]
[root@master
bkeep]# ./reorder.sh
fruit
price/lbs
quantity
banana
$0.89
100
peach
$0.79
65
REORDER
kiwi
$1.50
22
* REORDER
pineapple
$1.29
35
* REORDER
apple
$0.99
78
}
若expression为真,则执行actions
[root@master
bkeep]# awk 'BEGIN { x=0;while(x<3) {x+=1;[/b]print x;}}' //先给x+1再输出
1
2
3
[root@master
bkeep]# awk 'BEGIN { x=0;while(x<3) {print
x;x++[/b]}}'
//先输出再给x+1
0
1
2
Tips[/b]:do[/b]语句是while[/b]语句衍生出来的;区别在于do[/b]至少执行一次,while[/b]有可能不执行[/b]
(initialize_counter;
test_counter;increment_counter)
{
action
}
解释一下,呵呵
for (初始化计数器变量;测试计数器是否到顶了;增加计数器的值) {
要执行的动作!
}
【常用】例子:循环迭代处理记录中的域并输出他们
[root@master
bkeep]# cat for2.sh
#!/bin/bash
awk '{
for (x=1;x<=NF;x+=1) {
printf "%s
",$x "zbb";
}
printf "\n";
}'
fruit_prices.txt
[root@master
bkeep]# ./for2.sh
fruitzbb
price/lbszbb
quantityzbb
bananazbb
$0.89zbb
100zbb
peachzbb
$0.79zbb
65zbb
根据输出我们重点理解下awk中for循环的执行过程
1)读取一行数据
2)执行for循环,处理每一个字段,将其输出,退出for循环
3)执行第二个action即输出一个换行符
4)重复1~3,直到处理完所有行!
例子:倒序显示记录中的每个行
方法一:用for[/b]实现[/b]
#!/bin/bash
awk '
{a[NR]=$0};
//第一个action:把记录存储在一个数组里面
END{for
(x=NR;x>0;x-=1) {
//第二个action:for循环,x=NR总行数
printf "%s\n",a[x];
//如果x>0,则x=x-1,倒序输出a[x]数组中的内容!
}
}'
fruit_prices.txt //要处理的文件名!
方法2[/b]:用while[/b]实现[/b]
#!/bin/bash
awk '
{line[NR] = $0 }
//把所有记录都存放到数组里面
END {var=NR
//把总行数赋给变量var
while (var
> 0){ //当var大于0时,执行后面的action
print
line[var]
var--
//var=var-1
}}
'
fruit_prices.txt
//文件名
执行结果:[/b]
[root@master
bkeep]# ./re.sh
apple
$0.99
78
pineapple
$1.29
35
kiwi
$1.50
22
peach
$0.79
65
banana
$0.89
100
fruit
price/lbs
quantity
/usr/local/bkeep/shell.sh 001 002
I'm $0
is:/usr/local/bkeep/shell.sh
//正在被执行脚本的名字;`basename $0`
I'm $1
is:001
//$1接收到的参数
I'm $2
is:002
//$2接收到的参数
I'm $#
is:2
//总共接收到的参数个数
I'm $* is:001
002
//把接收到的参数全部打印出来
I'm $@ is:001
002
//同上
I'm $?
is:0
//上一个脚本的退出状态“0”代表正常;“1”非正常退出
I'm $$
is:24137
//当前执行脚本的进程ID
I'm $!
is:
//前一个后台[/b]进程的id
例子:再进一步解释下$*和$@吧;仔细看下面的例子,我就不废话了!
[root@master
bkeep]# cat shell.sh
#!/bin/bash
cc=$*
echo "I'm \$1
is:$1"
echo "I'm \$2
is:$2"
echo "I'm \$*
is:$*"
echo "I'm \$4
is:$4"
[root@master
bkeep]# ./shell.sh 11 22 33 "44" 55
I'm $1
is:11
I'm $2
is:22
I'm $* is:11 22 33
44 55
I'm $4
is:44
应用例子:统计文件中的空行数
[root@master
bkeep]# cat for.sh
#!/bin/bash
for i in
$@;
//这里我们不知道有多少个文件需要统计,所以用$@来接收参数!
do
if
[ -f $i ]; then
echo $i
awk ' /^$/ { x=x+1;} END{print x;}' $i
else
echo "ERROR:$i not a file."
>&2
fi
done
[root@master
bkeep]# ./for.sh aa bb
aa
//文件名为aa
7
//空行数7
bb
//文件名为bb
4
//空行数为4
导读:[/b]
1,awk基本语法
2,比较操作符
3,复合表达式
4,next命令
5,变量及变量赋值
6,awk中的赋值操作符
7,BEGIN和END
8,内置变量
9,awk使用shell变量
10,awk中的三种流控制语句
10.1 if语句
10.2 while语句:
10.3 for语句:
11,实验:
12,shell里的特殊变量
正文:[/b]
1,awk基本语法
awk ‘script’ filesscript
由下面的结构组成 /pattern/{actions}
例子:打印fruit_prices.txt文件的内容
[root@master
bkeep]# awk '{print;}' fruit_prices.txt
fruit
price/lbs
quantity
banana
$0.89
100
peach
$0.79
65
kiwi
$1.50
22
pineapple
$1.29
35
apple
$0.99
78
TIPS:[/b]留意printf[/b]的用法
[/b]如果加“-[/b]”说明是左对齐![/b]
[root@master
bkeep]# awk '{printf "%-15s[/b] %s\n", $1, $3;}'
fruit_prices.txt
fruit
quantity
banana
100
peach
65
kiwi
22
pineapple
35
apple
78
留意printf[/b]的用法
[/b]如果不加“-[/b]”说明是右对齐![/b]
[root@master
bkeep]# awk '{printf "s[/b] %s\n", $1, $3;}'
fruit_prices.txt
fruit quantity
banana 100
peach 65
kiwi 22
pineapple 35
apple 78
例子:给价格高于1美元的水果加个星号
[root@master
bkeep]# cat fruit_prices.txt
fruit
price/lbs
quantity
banana
$0.89
100
peach
$0.79
65
kiwi
$1.50
22
pineapple
$1.29
35
apple
$0.99
78
[root@master
bkeep]# cat price.sh
#!/bin/bash
awk '
/
*\$[1-9][0-9]*\.[0-9][0-9] */ {print $1,$2,$3,"*";} //[/b]星号前面一定要留空格,否则匹配不到[/b]
/
*\$0\.[0-9][0-9] */ {print;}
//[/b]以后养成习惯,/ key /[/b]斜杠和key[/b]之间始终留空格[/b]
'
fruit_prices.txt
执行结果:
[root@master
bkeep]# ./price.sh
banana
$0.89
100
peach
$0.79
65
kiwi $1.50 22
*
pineapple $1.29 35
*
apple
$0.99
78
上面的格式很不好看,我们改改它吧!
TIPS[/b]:[/b]$0[/b]:[/b]awk[/b]使用变量[/b]0[/b]原原本本地存储它所读入的整个输入行。这样可以保持和原来文本格式相同的输出[/b]
[root@master
bkeep]# cat price.sh
#!/bin/bash
awk '
/
*\$[1-9][0-9]*\.[0-9][0-9] */ {print $0[/b],"*";}
/
*\$0\.[0-9][0-9] */ {print;}
'
fruit_prices.txt
[root@master
bkeep]# ./price.sh
banana
$0.89
100
peach
$0.79
65
kiwi
$1.50
22 *
pineapple
$1.29
35 *
apple
$0.99
78
2,比较操作符
语法:expression{actions;}
expression[/b]
可以使用以下操作符构成[/b]
< [/b]
小于[/b]
> [/b]
大于[/b]
<= [/b]
小于等于[/b]
>= [/b]
大于等于[/b]
== [/b]
等于[/b]
!= [/b]
不等于[/b]
value ~ /pattern/ [/b]
若value[/b]匹配pattern[/b]则为真[/b]
value !~ /pattern/ [/b]
若value[/b]不匹配pattern[/b]则为真[/b]
说明:$2 ~ /^\$[1-9][0-9]* [/b]
将匹配第二列以$[/b]开头,然后大于1[/b]的二位数。(注意,这里是1[/b]而不是10[/b])[/b]
例子:给数量大于50的水果加星号
[root@master
bkeep]# cat larger.sh
#!/bin/bash
awk '
$3>50[/b]
{printf "%s\t%s\n",
$0,"*"}[/b]
$3<=50 {printf "%s\n",$0}
'
fruit_prices.txt
[root@master
bkeep]# ./larger.sh
fruit
price/lbs
quantity
*[/b]
banana
$0.89
100
*
peach
$0.79
65
*
kiwi
$1.50
22
pineapple
$1.29
35
apple
$0.99
78
*
3,复合表达式
语法:(compoundexpression)
(expr1)&&
(expr2)
-------
与
(expr1)|| (expr2) -------
或
说明一下:符合表达式必须用括号括起来[/b]
当使用&&[/b]时,expr1[/b]和expr2[/b]必须同时为零(零代表真!呵呵~),复合表达式才为真;[/b]
当使用 ||[/b]
时,expr1[/b]和expr2[/b]
只要有一个为真,复合表达式则为真![/b]
例子:显示价格高于1美元且数量少于50的水果记录,给打个标记!
[root@master
bkeep]# cat larger.sh
#!/bin/bash
awk '
($2 ~
/^\$[1-9][0-9]*\.[/b][0-9][0-9]$/)
&& ($3<50)
{
//这是一个模式匹配(请参阅比较操作符
printf
"%s\t%s\t%s\n", $0,"*","reorder";
}
'
fruit_prices.txt
[root@master
bkeep]# ./larger.sh
kiwi
$1.50
22
*
reorder
pineapple
$1.29
35
*
reorder
4,next命令
例子:给库存少于50的水果价格标签!
[root@master
bkeep]# cat next.sh
#!/bin/bash
awk '
$3
<= 50 { printf "%s\t%s\n",$0,"REORDER" ;
}
$3
> 50 {print $0; }
'
fruit_prices.txt
当输入行为:kiwi
$1.50
22
脚本执行以下过程:
1)检查是否第三列的值22小于50,由于值小于50,执行脚本的第二步
2)打印该行,并在行尾添加REORDER标志
3)检查是否第三列的值22大于50,由于值不大于50,脚本读下一行
呵呵,傻子都看得出这种情况下执行第三步是多余的。那么如何跳过呢?可以使用next命令。
next[/b]命令:告诉awk[/b]跳过剩下的所有模式和表达式,并读取输入的下一行,同时从第一个模式或表达式开始处理该行![/b]
修改后的脚本,加入了next[/b]命令![/b]
[root@master
bkeep]# cat next.sh
#!/bin/bash
awk '
$3
<= 50 { printf "%s\t%s\n",$0,"REORDER" ;next;[/b] }
$3
> 50 {print $0; }
'
fruit_prices.txt
[root@master
bkeep]# ./next.sh
fruit
price/lbs
quantity
banana
$0.89
100
peach
$0.79
65
kiwi
$1.50
22
REORDER
pineapple
$1.29
35
REORDER
apple
$0.99
78
现在脚本执行如下;
1)检查是否第三列的值22小于50,由于值小于50,所以执行脚本第二步
2)打印输出行并在该行后打印REORDER标志(有了[/b]next[/b]后就不再执行$3 > 50 {print $0;
}[/b])
3)读取下一输入行并从第一种模式开始
5,变量及变量赋值
下面给变量赋值fruit=100
//把数字赋给fruit变量
fruit=”peach” //把字符串赋给fruit变量
fruit=$1
//把第一列赋给fruit变量
awk[/b]中的数字操作符:[/b]
+ [/b]
加[/b]
- [/b]
减[/b]
* [/b]
乘[/b]
/ [/b]
除[/b]
% [/b]
求余[/b]
^ [/b]
求幂[/b]
应用例子:统计文件中的空行数
[root@master
bkeep]# cat for.sh
#!/bin/bash
for i in
$@;
//这里我们不知道有多少个文件需要统计,所以用$@来接收参数!
do
if
[ -f $i ]; then
echo $i
awk ' /^$/ { x=x+1;} END{print x;}' $i
else
echo "ERROR:$i not a file."
>&2
fi
done
[root@master
bkeep]# ./for.sh aa bb
aa
//文件名为aa
7
//空行数7
bb
//文件名为bb
4
//空行数为4
6,awk中的赋值操作符
+=x+=1
就是x=x+1
-=
x-=1
就是x=x-1
*=
x*=1
就是x=x*1
/=
x/=1
就是x=x/1
%=
x%=2
就是x=x%2
^=
x^=2
就是x=x^2
7,BEGIN和END
awk的语法:/pattern/ {action}pattern:模式
这里pattern有两个特殊模式BEGIN和END
下面是BEGIN
END的语法:
awk ‘
BEGIN { actions
}
/ pattern / {
actions }
/ pattern / {
actions }
END { actions
}
‘ files
BEGIN和END都是可选的
·当指定BEGIN模式时,awk在读取任何输入前执行动作
actions
·当指定END模式时,awk在其退出前执行动作actions
这里要特别注意:比如awk读入aa.txt。那么BEGIN只在读入aa时执行一次,然后按行处理的时候不再执行BEGIN指定的action!(也可以这么理解:BEGIN只对文件生效,而不是按行生效!!);理解了BEGIN,END还会糊涂吗?呵呵!
8,内置变量
gawk语言中有几个十分有用的内置变量,现在列于下面:NR[/b]
已经读取过的记录数。[/b]
FNR[/b]
从当前文件中读出的记录数。[/b]
FILENAME[/b]
输入文件的名字。[/b]
FS[/b]
字段分隔符(缺省为空格)。[/b]
RS[/b]
记录分隔符(缺省为换行)。[/b]
OFMT[/b]
数字的输出格式(缺省为[/b]% g[/b])。[/b]
OFS[/b]
输出字段分隔符。[/b]
ORS[/b]
输出记录分隔符。[/b]
NF[/b]
当前记录中的字段数。[/b]
如果你只处理一个文件,则NR
和FNR
的值是一样的。但如果是多个文件, NR是对所有的文件来说的,而FNR
则只是针对当前文件而言。
例子:统计空行的脚本:[/b]
[root@master
bkeep]# cat for.sh
#!/bin/bash
for i in
$@;
do
if
[ -f $i ]; then
#
echo $i
awk 'BEGIN { printf "%s\t",FILENAME;} //输出文件名
/^$/ { x+=1;}
//统计空行
END{avg=100*(x/NR); printf "%s\t%3.1f\n",x,avg;}' $i //最后算百分比及打印结果
else
echo "ERROR:$i not a file."
>&2
fi
done
[root@master
bkeep]# ./for.sh aa bb //显示出来的结果很漂亮。可惜了,文件名没出来!
7
87.5
//怀疑FILENAME内置变量被修改了???
4
57.1
9,awk使用shell变量
经过前面的学习,我们知道shell变量的引用由$xxx实现,而awk中的变量直接使用xxx来引用。所以我们就要思考如何让awk使用shell变量
语法:[/b]
awk ‘script’
awkvar1=value awkvar2=value
......
files[/b]
说明: awk[/b]:[/b]
命令;[/b]
‘script[/b]’:awk[/b]将要执行的脚本;
awkvarN[/b]:awk[/b]的变量;value[/b]:shell[/b]中的变量值;
files[/b]:将要处理的文件名[/b]
【重点实验—[/b]记忆】[/b]
例子:根据用户提供的水果数量,将低于这个值的水果打印出来!
[root@master
bkeep]# cat awk_var.sh
#!/bin/bash
NUM_FRUIT="$1"
//将用户输入传递给shell变量NUM_FRUIT
if [ -z
"$NUM_FRUIT" ]; then NUM_FRUIT=75;fi //如果用户没有输入,则赋默认值75
awk '
$3 <= num_fruit {print;}
//最终将用户输入传递给awk变量num_fruit
' num_fruit="$NUM_FRUIT"[/b]
fruit_prices.txt
//通过此方法将$NUM_FRUIT
//赋值给num_fruit;即把shell变量赋给awk
执行结果:[/b]
[root@master
bkeep]# ./awk_var.sh 40
//将数量低于40的水果打印出来
kiwi
$1.50
22
pineapple
$1.29
35
[root@master
bkeep]# ./awk_var.sh 30
//将数量低于30的水果打印出来
kiwi
$1.50
22
10,awk中的三种流控制语句
if语句while语句
for语句
10.1 if语句
if (expression1){action1}
else if (expression2)
{action2}
else { action3}
执行过程:[/b]
1)计算expression1的值
2)若expression1为真,执行action1并推出if语句
3)若expression1为假,计算expression2
4)若expression2为真,执行action2并退出if语句
5)若expression2为假,执行action3并退出if
举例:若水果价格高于1美元,那么给它加星号;若水果数量少于50,则给它加REORDER
[root@master
bkeep]# cat reorder.sh
#!/bin/bash
awk '{
printf "%s\t",$0;
if
( $2 ~ /\$[1-9][0-9]*\.[0-9][0-9]/ ) {
printf " * ";
if ($3 <= 75) {
printf "REORDER\n";
} else {
printf "\n";
}
}else {
if ($3<=75) {
printf "REORDER\n";
}else {
printf "\n";
}
}
}'
fruit_prices.txt
执行结果:[/b]
[root@master
bkeep]# ./reorder.sh
fruit
price/lbs
quantity
banana
$0.89
100
peach
$0.79
65
REORDER
kiwi
$1.50
22
* REORDER
pineapple
$1.29
35
* REORDER
apple
$0.99
78
10.2 while语句:
while (expression) { actions}
若expression为真,则执行actions
[root@master
bkeep]# awk 'BEGIN { x=0;while(x<3) {x+=1;[/b]print x;}}' //先给x+1再输出
1
2
3
[root@master
bkeep]# awk 'BEGIN { x=0;while(x<3) {print
x;x++[/b]}}'
//先输出再给x+1
0
1
2
Tips[/b]:do[/b]语句是while[/b]语句衍生出来的;区别在于do[/b]至少执行一次,while[/b]有可能不执行[/b]
10.3 for语句:
for(initialize_counter;
test_counter;increment_counter)
{
action
}
解释一下,呵呵
for (初始化计数器变量;测试计数器是否到顶了;增加计数器的值) {
要执行的动作!
}
【常用】例子:循环迭代处理记录中的域并输出他们
[root@master
bkeep]# cat for2.sh
#!/bin/bash
awk '{
for (x=1;x<=NF;x+=1) {
printf "%s
",$x "zbb";
}
printf "\n";
}'
fruit_prices.txt
[root@master
bkeep]# ./for2.sh
fruitzbb
price/lbszbb
quantityzbb
bananazbb
$0.89zbb
100zbb
peachzbb
$0.79zbb
65zbb
根据输出我们重点理解下awk中for循环的执行过程
1)读取一行数据
2)执行for循环,处理每一个字段,将其输出,退出for循环
3)执行第二个action即输出一个换行符
4)重复1~3,直到处理完所有行!
11,实验:
例子:倒序显示记录中的每个行
方法一:用for[/b]实现[/b]
#!/bin/bash
awk '
{a[NR]=$0};
//第一个action:把记录存储在一个数组里面
END{for
(x=NR;x>0;x-=1) {
//第二个action:for循环,x=NR总行数
printf "%s\n",a[x];
//如果x>0,则x=x-1,倒序输出a[x]数组中的内容!
}
}'
fruit_prices.txt //要处理的文件名!
方法2[/b]:用while[/b]实现[/b]
#!/bin/bash
awk '
{line[NR] = $0 }
//把所有记录都存放到数组里面
END {var=NR
//把总行数赋给变量var
while (var
> 0){ //当var大于0时,执行后面的action
line[var]
var--
//var=var-1
}}
'
fruit_prices.txt
//文件名
执行结果:[/b]
[root@master
bkeep]# ./re.sh
apple
$0.99
78
pineapple
$1.29
35
kiwi
$1.50
22
peach
$0.79
65
banana
$0.89
100
fruit
price/lbs
quantity
12,shell里的特殊变量
# sh/usr/local/bkeep/shell.sh 001 002
I'm $0
is:/usr/local/bkeep/shell.sh
//正在被执行脚本的名字;`basename $0`
I'm $1
is:001
//$1接收到的参数
I'm $2
is:002
//$2接收到的参数
I'm $#
is:2
//总共接收到的参数个数
I'm $* is:001
002
//把接收到的参数全部打印出来
I'm $@ is:001
002
//同上
I'm $?
is:0
//上一个脚本的退出状态“0”代表正常;“1”非正常退出
I'm $$
is:24137
//当前执行脚本的进程ID
I'm $!
is:
//前一个后台[/b]进程的id
例子:再进一步解释下$*和$@吧;仔细看下面的例子,我就不废话了!
[root@master
bkeep]# cat shell.sh
#!/bin/bash
cc=$*
echo "I'm \$1
is:$1"
echo "I'm \$2
is:$2"
echo "I'm \$*
is:$*"
echo "I'm \$4
is:$4"
[root@master
bkeep]# ./shell.sh 11 22 33 "44" 55
I'm $1
is:11
I'm $2
is:22
I'm $* is:11 22 33
44 55
I'm $4
is:44
应用例子:统计文件中的空行数
[root@master
bkeep]# cat for.sh
#!/bin/bash
for i in
$@;
//这里我们不知道有多少个文件需要统计,所以用$@来接收参数!
do
if
[ -f $i ]; then
echo $i
awk ' /^$/ { x=x+1;} END{print x;}' $i
else
echo "ERROR:$i not a file."
>&2
fi
done
[root@master
bkeep]# ./for.sh aa bb
aa
//文件名为aa
7
//空行数7
bb
//文件名为bb
4
//空行数为4
相关文章推荐
- awk】1-awk基础篇(又名UNIX.Shell.awk)
- <<UNIX环境高级编程>>学习总结——第一章:UNIX基础知识
- awk基础知识--目录
- [基础]Linux/Unix用户(组)管理命令
- 最近研究UNIX收获:(高手免进,挺基础的)
- UNIX基础知识之出错处理
- 【视频教学】学习Oracle前的准备知识和Unix基础
- unix基础之改变文件权限
- UNIX基础--用户和基本账户管理
- unix编程基础知识
- awk命令基础操作
- shell基础九:awk
- 开发环境入门 linux基础 (部分)awk 赋值变量 if
- Unix awk命令(2) -- awk命令手册
- awk基础学习
- 类UNIX系统基础:文件安全与权限
- 算法Sedgewick第四版-第1章基础-025-用队列实现unix下的Directory命令
- Unix awk使用手册
- 1、UNIX基础知识
- linux基础--awk文本分析工具详解