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的不同的语法元素:

二元的操作符:

OperatorTypeMeaning
+ Arithmetic Addition
- Arithmetic Subtraction
* Arithmetic Multiplication
/ Arithmetic Division
% Arithmetic Modulo
<space> String Concatenation

 

使用范例如下:

ExpressionResult
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;

类似的操作符有:

OperatorMeaning
+= Add result to variable
-= Subtract result from variable
*= Multiply variable by result
/= Divide variable by result
%= Apply modulo to variable

 

条件表达式:

这些操作符可以用于if和while这些表达式当中:

OperatorMeaning
== Is equal
!= Is not equal to
> Is greater than
>= Is greater than or equal to
< Is less than
<= Is less than or equal to

 

正则表达式:

OperatorMeaning
~ 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(文件名)"

 

posted @ 2017-05-10 20:38  WenYao.Huang  阅读(266)  评论(0编辑  收藏  举报