awk用法
原文地址: http://www.grymoire.com/Unix/Awk.html#uh-0
基本结构:
awk程序都是如此的一个基本结构:
pattern { action }
pattern指定,action是什么时候执行的。AWK是以行为导向的。pattern就是指定了,在每一个行作为输入的时候,进行一个测试。条件为真,就会采取行动。
没人的pattern是匹配每一行。这就是blank或者是NULL pattern。除此之外的两个模式是BEGIN和END。这两个的意思是,在一个行作为输入之前或之后进行指定的动作。
BEGIN { print "START" } { print } END { print "STOP" }
这个脚本没有什么用,但是作为修改之后,如下面:
#!/usr/bin/awk -f BEGIN { print "File\tOwner"} { print $8, "\t", $3} END { print " - DONE -" }
\t 指的是一个tab
"$8"和"$3"指的是第几个变量(输入行的域,列),和脚本差不多。
将上面的代码保存为脚本FileOwner,并且设置可执行全县,然后使用
ls -l | FileOwner
还可以直接写成脚本:
#!/bin/bash -f # Linux users have to change $8 to $9 awk '\ BEGIN { print "File\tOwner" } \ { print $8, "\t", $3} \ END { print " - DONE -" } \ '
简单用法:
如何使用变量定义列
#!/bin/bash column=1 awk '{print $'$column'}'
默认值的用法:
#!/bin/bash # Linux users have to change $8 to $9 column=${3:-4} awk '{print $'$column'}'
这节讨论以下awk的不同的语法元素:
二元的操作符:
Operator | Type | Meaning |
---|---|---|
+ | Arithmetic | Addition |
- | Arithmetic | Subtraction |
* | Arithmetic | Multiplication |
/ | Arithmetic | Division |
% | Arithmetic | Modulo |
<space> | String | Concatenation |
使用范例如下:
Expression | Result |
---|---|
7+3 | 10 |
7-3 | 4 |
7*3 | 21 |
7/3 | 2.33333 |
7%3 | 1 |
7 3 | 73 |
awk没有类型的概念。
"123"字符串,随时回转换为数字123. "123X" 会转换为0(不同的awk有不同的定义。也有可能是123.)
单个操作符:
"+" and "-" operators 用于表示正负。
自增和自减操作符
"++" 和 "--" 行为和C语言一样。
赋值操作符:
variable = arithmetic_expression
x=1+2*3 4; 的顺序 等于 x = (1 + (2 * 3)) "4";
x=x+2; 等于 x+=2;
类似的操作符有:
Operator | Meaning |
---|---|
+= | Add result to variable |
-= | Subtract result from variable |
*= | Multiply variable by result |
/= | Divide variable by result |
%= | Apply modulo to variable |
条件表达式:
这些操作符可以用于if和while这些表达式当中:
Operator | Meaning |
---|---|
== | Is equal |
!= | Is not equal to |
> | Is greater than |
>= | Is greater than or equal to |
< | Is less than |
<= | Is less than or equal to |
正则表达式:
Operator | Meaning |
---|---|
~ | Matches |
!~ | Doesn't match |
使用例子:
word !~ /START/
lawrence_welk ~ /(one|two|three)/
and/or/not
"&&" and "||" and "!"
awk的命令
if ( conditional ) statement [ else statement ] while ( conditional ) statement for ( expression ; conditional ; expression ) statement for ( variable in array ) statement break continue { [ statement ] ...} variable=expression print [ expression-list ] [ > expression ] printf format [ , expression-list ] [ > expression ] next exit
用于打印平方(这是能够在linux上bash和gawk运行的,和原文有区别)
#!/bin/awk -f BEGIN { # Print the squares from 1 to 10 the first way i=1; while (i <= 10) { printf "The square of " i " is " i*i "\n"; i = i+1; } # do it again, using more concise code for (i=1; i <= 10; i++) { printf "The square of " i " is " i*i "\n"; } # now end exit; }
还有另外一个尝试的版本:
#!/bin/awk -f BEGIN { # Print the squares from 1 to 10 the first way i=1; while (i <= 10) { print "The square of ", i ," is ", i*i, "\n"; i = i+1; } # do it again, using more concise code for (i=1; i <= 10; i++) { printf "The square of " i " is " i*i "\n"; } # now end exit; }
在这里,第一个,我注意到 变量i 使用的时候, 就只需要打出i就可以了。
第二个,print 可以使用逗号(,)来进行连接, printf使用空格( )来进行连接字符串。
第二个接受一个参数,然后返回平方:
#!/bin/awk -f BEGIN { print "type a number"; } { print "The square of ", $1, " is ", $1*$1; print "type another number"; } END { print "Done" }
这个程序汇呈现循环的方式来进行的,问了一个又一个。
结果
type a number 12 The square of 12 is 144 type another number 22 The square of 22 is 484 type another number 33 The square of 33 is 1089 type another number
可以这样使用:
$ echo 1 | ./awk.example.1.bash type a number The square of 1 is 1 type another number
下面是这样一个程序, 他清点所有的行数,并且把第一列的行的数加起来,并且计算平均值
$ wc -c * 414 awk.example.1.bash 304 awk.example.1.bash~ 94 FileOwner 0 FIleOwner~ 825 Makefile 1637 total
然后
wc -c * | ./awk.example.1.bash 6 lines read total is 3274 average is 545.667
awk的内置变量:
有两种变量,第一个是用户定义的,第二个是位置变量。
位置变量不是一个特殊的变量,而是由美元符号($)所开头的一个变量。
因此:
#!/bin/awk -f
BEGIN {
print $1; # 输出第一个位置变量
X=1;
print $X; # 同样也是输出第一个位置变量
print X # 输出变量X
}
有一个特殊的变量: $0,所指的是输出所有awk所读入的整行
如果你输入了8个域,在一行,就等于
print $0; print $1, $2, $3, $4, $5, $6, $7, $8
要注意,这个不要在BEGIN上面用,是没有用的哦
#!/bin/awk -f BEGIN { print $0; # 完全每输出 } { print $0; }
你也可以修改这个域的值为空,如下
$ wc -c * 40 awk.example.1.bash 304 awk.example.1.bash~ 94 FileOwner 0 FIleOwner~ 825 Makefile 1263 total #!/bin/awk -f { $2=""; print; } $ wc -c * | ./awk.example.1.bash 77 304 94 0 825 1300
和以下对比:
#!/bin/awk -f { print $1; } wc -c * | ./awk.example.1.bash 32 304 94 0 825 1255 [andrew@andrew 2]$
结果是一样的,但是不完全一样。我也不知道有什么不一样阿。
FS 输入的分割符
awk的-F可以用来作为分割符:
awk -F: '{if ($2 == "") print $1 ": no password!"}' < /etc/passwd
这个把一行根据:来进行分域。
同样的,可以使用FS作为分割符
#!/bin/awk -f BEGIN { FS=":"; } { if ( $2 == "" ) { print $1 ": no password!"; } } # 使用方法 $ ./awk.example.1.bash < /etc/passwd
这时候再使用-F选项是没有用的。因为直接调用了"#!/bin/awk -f"
还有一个优点就是,可以i设置多于一个的分割符。
# 文本 ONE 1 I TWO 2 II #START THREE:3:III FOUR:4:IV FIVE:5:V #STOP SIX 6 VI SEVEN 7 VII # 处理的脚本 #!/bin/awk -f { if ($1 == "#START") { FS=":"; } else if ($1 == "#STOP") { FS=" "; } else { #print the Roman number in column 3 print $3 } }
以下另外一个脚本,输出比较奇怪
# 文本 # One Two:Three:4 Five #!/bin/awk -f { print $2 FS=":" print $2 } # 输出: Two:Three:4 Two:Three:4 #!/bin/awk -f { FS=":" print $2 } # 输出 Three
原因就是: 在读入输入之前改变FS,是有效的;在读入之后,就不会再有效了。默认FS是空格
但是能使用这个方法来进行动态定义:
#!/bin/awk -f { if ( $0 ~ /:/ ) { FS=":"; $0=$0 } else { FS=" "; $0=$0 } #print the third field, whatever format print $1 } # 输出 One Two
OFS 输出域的分割符
#!/bin/awk -f { # 只会输出第一个域,这是因为,空格连接的$2和$3,然后输出的时候没有一个空格 print $2 $3 # 输出两个域,第二个awk会在,号中放入一个空格(默认的OFS就是空格) print $2, $3 }
在输出的时候取消密码,可以这么做
#!/bin/awk -f BEGIN { FS=":"; OFS=":"; } { $2=""; print }
getline的用法,遇到结尾的时候,返回0
从文件中读入:
getline < "secondary.input(文件名)"