感谢支持
我们一直在努力

Shell脚本之awk文本编辑器语法

AWK  ——是一种用于处理文本的编程语言工具。
    英文原义:Aho、Weinberger、Kernighan
    中文释义:三位创造者Aho、Weinberger和Kernighan统称

    AWK 在很多方面类似于 shell 编程语言,尽管 AWK 具有完全属于其本身的语法。最初创造 AWK 时,其目的是用于文本处理,并且这种语言的基础是,只要在输入数据中有模式匹配,就执行一系列指令。该实用工具扫描文件中的每一行,查找与命令行中所给定内容相匹配的模式。如果发现匹配内容,则进行下一个编程步骤。如果找不到匹配内容,则继续处理下一行。

    awk 之所以成为一种优秀的程序设计语言的原因之一是内置函数的使用,awk定义并支持了一系列的内置函数,由于这些函数的使用,使得awk提供的功能更为完善和强大。

常用语法:
    awk    [options]    ‘commands’        testfiles
   
options选项
    -F    定义字段分隔符,默认分隔符为连续空格或制表符
        用$1,$2,$3等顺序表示files中每行以间隔符号分隔的各列不同域
    -v    定义变更并赋值,也可以借用次方式从shell变量中引入变量
使用示例:
[root@localhost test]# awk -F”:” ‘{print $1,$7}’ testfile
        以冒号作为分隔符,打印第1和第7个字段
[root@localhost test]# awk -F”[:/]” ‘{print $1,$7}’ testfile
        以冒号或斜杠 / 作为分隔符,打印第1第7个字段
[root@localhost test]# awk -F”:/” ‘{print $1,$7}’ testfile
        以冒号加斜杠 “:/”整体作为分隔符
       
———————————————————–   
command
    读前处理    行处理        读后处理
        1、读前处理    BEGIN{awk_cmd1;awk_cmd2;}
        2、行处理:定址    命令
        定址方法:正则,变量,比较,关系运算
                正则需要用 / / 包裹起来
        常用正则:
            ^    行首                $    行尾
              .    除了换行符以外的任意单个字符
              *    前导字符的零个或多个
              .*    所有字符
              []    字符组内的任一字符
              [^]    对字符组内的每个字符取反(不匹配字符组内的每个字符)
              ^[^]    非字符组内的字符开头的行
              [a-z] 小写字母
              [A-Z] 大写字母
              [a-Z] 小写和大写字母
              [0-9] 数字
              \<    单词头,以空格或特殊字符做分隔,连续的字符串被当做单词
              \>    单词尾

        扩展正则
              ?        前导字符零个或一个
              +        前导字符一个或多个
              abc|def        abc或def
              a(bc|de)f        abcf 或 adef
              x\{m\}          x出现m次
              x\{m,\}          x出现m次至多次(至少m次)
              x\{m,n\}        x出现m次至n次

        NR变量定址,NR 表示AWK读入的行数
        FNR表示读入行所在文件中的行数
       
        逻辑运算——可直接引用域进行运算
            ==    >=    <=    !=    >    <    ~    !~
            如:# awk ‘NR==1 {print}’  /etc/passwd
                    root:x:0:0:root:/root:/bin/bash
                           
        命令    如:{print $1,$2}
       
    3、读后处理
        END {awk_cmd1;awk_cmd2;}

—————————————————————
AWk的变量
    NR    AWK处理的总行数
    FNR  AWK处理的当前文件的行数,非全部
    FS    字段分隔符,默认为连续空格或制表符,可以使用多个不同的符号做分隔符,也可在options出使用  -F[:/]    指定分隔符
    OFS  输出字符的分隔符 默认是空格
            如:# awk -F: ‘OFS=”***” {print $1,$2}’ /etc/passwd
                      root***x
    NF    当前读入行的字段个数
    ORS  输出行的分隔符,默认是换行
        # awk -F: ‘ORS=”***” {print $1,$2}’ /etc/passwd
        root x***bin x***
    FILENAME    当前文件名

更多详情见请继续阅读下一页的精彩内容: http://www.linuxidc.com/Linux/2013-11/92787p2.htm

相关阅读:

sed与awk常用功能 http://www.linuxidc.com/Linux/2013-06/86099.htm

Linux下shell编程常用grep\awk\sed语法 http://www.linuxidc.com/Linux/2013-07/87047.htm

Linux下Shell编程——awk编程 http://www.linuxidc.com/Linux/2013-06/85527.htm

文本处理工具awk详解 http://www.linuxidc.com/Linux/2013-05/84248.htm

Linux awk命令使用详解 http://www.linuxidc.com/Linux/2012-12/77082.htm

引用shell变量的方法:
(1)使用 -v 引用变量值
[root@localhost test]# a=5
[root@localhost test]# awk -v c=$a  -F:  ‘NR < c {print NR,$0}’ /etc/passwd
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
 
(2)把整个命令拆开传递,让shell变量外露
[root@localhost test]# a=5
[root@localhost test]# awk -F: ‘NR < ‘$a'{print NR,$0}’ /etc/passwd
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin

————————————————————
操作符
    赋值        =        +=        -=        /=        *=
    &&    ——逻辑与    ||——逻辑或    !——逻辑非
         
    匹配正则或不匹配,正则需要用 /正则/ 包围住
        ~          !~
    关系 比较字符串,要把字符串用双引号引起来
        <        <=    >    >=    !=        ==
    字段引用
        $    字段引用需要加$        而变量引用直接用变量名取
    运算符
        +    –    *    /    %        ++    —
    转义序列
        \\        \自身
        \$        转义$
        \t        制表符
        \b        退格符
        \r        回车符
        \n        换行符
        \c        取消换行

用法示例:
# awk -F: ‘$3 >= 30 && $3 <= 40 {print $0}’ /etc/passwd
        打印出uid在30到40之间的用户信息行
# awk -F: ‘ NR >= 30 && NR <= 40 {print NR,$0}’ /etc/passwd
        打印出行号在30到40之间的行
# awk -F: ‘ NR % 2 == 1 {print NR,$1,NF}’ /etc/passwd
        打印奇数行
# awk -F: ‘ NR % 2 == 0 {print NR,$1,NF}’ /etc/passwd
        打印偶数行
# awk -F: ‘ $3 != $4 {print NR,$1,$3,$4}’ /etc/passwd
        打印uid和gid不相等的用户信息行
# awk -F: ‘$7 ~ /bash/ {print NR,$1,$7}’ /etc/passwd
        打印第7个字段能匹配 /bash/ 字符串的行
# awk -F: ‘$7 !~ /nologin/ {print NR,$1,$7}’ /etc/passwd
        打印第7个字段不能匹配 /nologin/ 字符串的行
 
————————
数组

自定义数组
# awk ‘BEGIN{ary[1]=”hunan”;ary[2]=”hubei”;print ary[1],ary[2]}’
hunan hubei

# awk ‘BEGIN{ary[1]=”hunan”;ary[2]=”hubei”;for(i in ary) print ary[i]}’
hunan
hubei

环产生数组和取出数组
# awk ‘BEGIN{n=5;for (i=1;i<=n;i++) ary[i]=i+100;for(m in ary) print m,ary[m]}’
    4 104
    5 105
    1 101
    2 102
    3 103

# awk -F: ‘{ary[NR]=$1}END{for(i in ary){print i,ary[i]}}’ testfile
4 dbus
5 usbmuxd
6 hsqldb
7 avahi-autoipd
8 rpc
1 root
2 bin
3 myuser

# awk -F: ‘{ary[$3]=$1} END {for(i in ary) print i,ary[i]}’ testfil

流程控制
    分支结构
(一)    if    (条件)    动作
        if    (条件)    {动作1;动作2}
如:
# awk -F: ‘{if ($1 == “root”)print $1}’ /etc/passwd

awk -F: ‘{if ($1 == “root”){print $1;print $7}}’ /etc/passwd

(二)    if    (条件1)
        动作1
        else
        动作2
如:
# awk -F: ‘{if ($1 == “root”) print $1; else print $6}’  testfile
# awk -F: ‘{if ($1 == “root”) {print $1} else print $6}’  testfile
上面两个命令是等价的,要么用分号隔开,表示第一个动作体的结束,要么将动作体用大括号定位范围

(三)if    (条件1)
            动作1
        else    if (条件2)
            动作2
        else    if (条件2)
            动作3
        else
            动作4
           
如:
# awk -F: ‘{if ($1==”root”)print $1;else if($1==”bin”)print $3;else if($1==”myuser”)print $7}’ testfile
   
(四) 条件 ? 动作1:动作2
        expr ? action1:action2
如:
# awk  -F:  ‘AA=($3>=500?$3:”system_user”){print $1″\t”$3″\t”AA}’  testfile
root    0      system_user
bin          1        system_user
myuser    501    501

———————————————————-
读前处理和读后处理
   
如:
# awk  ‘BEGIN{i=1} {i++} END{print i}’  /etc/passwd

# awk -F: ‘BEGIN{print NR,NF} END{print NR,NF}’ /etc/passwd
0 0
46 7

# awk -F: ‘BEGIN{sum=0} {sum=sum+NF}END{print sum}’ /etc/passwd
322
# awk -F: ‘BEGIN{sum=0} {sum+=NF}END{print sum}’ /etc/passwd
322

BEGIN块可以独立使用,不需要引入文件
# awk  ‘BEGIN{i=1;while(i<10) {print i;i++}}’
1
2
3
4
5
6
7
8
9

————————————————————-
循环语句
(一)    while    (条件)
        {
            动作       
            条件运算
        }
如:
# awk -F: ‘{while($3<3) {print $3,$1;$3++}}’ /etc/passwd
0 root
1 root
2 root
1 bin
2 bin
2 daemon

(二) do    {
        动作
        条件运算   
    } while (条件)
如:
# awk ‘BEGIN{i=5;do{print i;i++}while(i<10)}’
5
6
7
8
9

(三)for    (预置;条件;递增)    {
            动作
        }
如:
# awk ‘BEGIN{for (i=1;i<5;i++) print i}’
1
2
3
4

(四) 循环for嵌套
如:
# awk ‘BEGIN{for (i=1;i<3;i++) {for (j=1;j<=3;j++) print i,j}}’
1 1
1 2
1 3
2 1
2 2
2 3

# awk ‘BEGIN{OFS=””;for (i=1;i<=9;i++) {for (j=0;j<=9;j++) {for (n=0;n<=9;n++) print i,j,n}}}’      使用嵌套的for循环,打印100-999之间的数   

# awk -F: ‘{for(x=NF;x>0;x–)print $x}’ testfile    逆序输出

————————————————————
输出样式
# awk -F: ‘{printf “%-10s %-7d %s\n”,$1,$3,$7}’ testfile
root          0          /bin/bash
bin            1          /sbin/nologin
myuser      501    /bin/bash
命令分析:
    %s是字符类型,%d数值类型
    printf默认是不输出换行的所以要加\n(printf和print不同,print默认每输出一行进行换行)
    10和7是偏移量
    默认是右对齐,所有加个- 就是左对齐,就是把不足的位数用空格填充
    注意:格式与输出列之间要有逗号

跳转语句
   
break 跳出循环
    # awk ‘BEGIN {for(x=1;x<5;x++) {if (x==3) break;print x }}’
    1
    2
   
continue 在达到循环底部之前终止当前循环 从新开始下一次循环
    # awk ‘BEGIN {for(x=1;x<5;x++) {if (x==3) continue;print x }}’
    1
    2
    4

next 读入下一行 同时返回脚本顶部 这样可以避免对当前行执行其他操作
    # awk -F: ‘NR > 5 {next} {print $1} END {print NR}’ /etc/passwd
    root
    bin
    daemon
    adm
    lp
    46
   
exit 使读取动作终止 并将控制移动到END,如果没有END则终止脚本
    # awk -F: ‘NR > 5 {exit} {print $1} END {print NR}’ /etc/passwd
    root
    bin
    daemon
    adm
    lp
    6

——————————————————————–
函数
转换函数,转换成整数
如:
# awk ‘BEGIN{print int(3.934)}’
3

随机数函数 rand()  srand()
rand() 取值 0 > r > 1 之间 默认的种子是系统时间 精确到秒
srand()取值 0 > r > 1 之间 可以指定种子来影响rand()取值数 默认是系统时间 精确到秒

echo $RANDOM
如:
# awk ‘BEGIN{print int(rand()*100)}’
23
# awk ‘BEGIN{srand(123);print int(rand()*100)}’
74
# awk -v a=$RANDOM ‘BEGIN{print a}’
22059

字符串函数
substr(s,x,y)
返回字符串s中从位置x起至y的子串,如果没有给出y,则从x开始到结束
如:
# awk  ‘BEGIN{aa=”abcdefghi”;print substr(aa,3,4)}’
cdef
# awk  ‘BEGIN{aa=”abcdefghi”;print substr(aa,1)}’
abcdefghi

大写小写函数
tolower()            小写函数
toupper()            大写函数
sprintf()    本身并不能打印,做格式转换,将数字转换成ASCII字符
# awk ‘BEGIN{for(i=97;i<=122;++i)print  toupper(sprintf(“%c”,i))}’
# awk ‘BEGIN{for(i=97;i<=122;++i)print  tolower(sprintf(“%c”,i))}’

字符串长度
length()      如果没有给定字符串则使用$0
# awk ‘BEGIN{print length(“abcdefghi”)}’
9
# awk ‘{print length()}’ /etc/passwd

gsub(/abc/,”ABC”,x)
 全局字符串替换,从x中用匹配的abc正则替换成ABC
# awk ‘BEGIN{aa=”abcxyzabcxyzabc”;gsub(/abc/,”ABC”,aa);print aa}’
ABCxyzABCxyzABC

系统交互输入函数——getline
(等同于shell中的read  -p  “strings”  var )
如:
# awk -F: ‘BEGIN{printf “sss: “;getline;for(i=1;i<=$0;i++) print i}’
sss: 4
1
2
3
4

使用getline函数将输入值赋给变量
# awk  -F: ‘BEGIN{printf “haoren: “;getline NUM;for(i=1;i<=NUM;i++)print NUM,i}’
haoren: 5
5 1
5 2
5 3
5 4
5 5

从文件中读入
#awk -F: ‘BEGIN {while (getline < “/etc/passwd” > 0) print $3″\t”$1}’
getline < “/etc/passwd” 从文件中读入,每次读取一行,默认情况下读取的次数等于awk自身引入文件的行数
            > 0      测试读取的返回值,成功返回1,失败返回-1,0文件末尾

从命令输出中输入
[root@stu254 ~]# awk ‘BEGIN {“uname -a”|getline ;print $3}’
2.6.18-53.el5

system(command)——引入系统命令,系统命令要用””引起来
如:
# awk ‘BEGIN{if(system(“mkdir mulu1”) != 0) print “error”}’
# awk ‘BEGIN{if(system(“mkdir mulu1”) != 0) print “error”}’
mkdir: 无法创建目录”mulu1″: 文件已存在
error

awk脚本——        -f
脚本开头使用  #!/bin/awk  -f
如:使用awk脚本添加用户
#!/bin/awk    -f
{
    system(“useradd  “$1”;echo “$2″|passwd –stdin”  $1)
}
# cat user.txt
myuser222 123123
myuser333 456456
# ./useradd.awk  user.txt
更改用户 myuser222 的密码 。
passwd: 所有的身份验证令牌已经成功更新。
更改用户 myuser333 的密码 。
passwd: 所有的身份验证令牌已经成功更新。

赞(0) 打赏
转载请注明出处:服务器评测 » Shell脚本之awk文本编辑器语法
分享到: 更多 (0)

听说打赏我的人,都进福布斯排行榜啦!

支付宝扫一扫打赏

微信扫一扫打赏