帝国CMS多值字段morevaluefield解密

图片 38

帝国CMS多值字段morevaluevield解密,深度解析帝国CMS多值字段技巧秘诀。

  • awk介绍
  • awk变量
  • printf命令:实现格式化输出
  • 操作符
  • awk pattern
  • awk action
  • awk数组
  • awk函数
  • awk脚本

  awk,逐行处理文本内容。Linux里的awk其实是“gawk”。

基本概述

一、awk介绍

  • 功能:
    报告生成器,模式化文本输出
    同时也是一门语言:模式扫描和处理语言

  使用格式:

帝国CMS7.0新增了多值字段。像下载地址、在线地址、图片集等这样的将多个内容存放到一个字段的功能,增加字段时选择多值表单元素即可,功能更强大,扩展更灵活。

(一)awk的基本语法概念

  • 基本格式:

awk [options] 'program' file…
awk [options] -f program_file file…
  • program通常由:BEGIN语句块、能够使用模式匹配的通用语句块、END语句块,共3部分组成,通常放置于单引号或双引号中

    • program格式:BEGIN{ action;… } pattern{ action;… } END{ action;…
      }
    • pattern:决定动作语句何时触发及触发事件
    • action statements:对数据进行处理,放在{}内指明
  • 选项:
    -F:指明输入时用到的字段分隔符,默认以空格作为分隔符
    -v var=value:自定义变量

  • 分割符、域和记录

    • 文件的每一行称为记录,每一列称为字段(域)
    • awk执行时,由分隔符分隔的字段(域)称为域标识,标记为$1,$2..$n,$0为所有域。
    • 注意:此处的$与shell中变量$符号含义不同
    • 省略action,则默认执行print $0 的操作

    awk [选项]
‘模式匹配 {命令 命令参数}’ file1, file2, ……

支持设定无限列与无限行数据录入,并且支持设置必填的列,以及默认行数。

(二)awk的工作原理

  • 第一步:执行BEGIN{action;… }语句块中的语句

    • BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中
  • 第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ action;…
    }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。

    • pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern语句块,则默认执行{
      print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块
  • 第三步:当读至输入流末尾时,执行END{action;…}语句块

    • END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块

 

结构分析

(三)print语句

  • 语法:print item1, item2, …

    • 逗号分隔符
    • 输出的各item可以字符串,也可以是数值;当前记录的字段、变量或awk的表达式
    • 省略item,相当于print $0
  • 示例1-1:

awk '{print "hello, awk"}'           //等待输入,每输入一条打印一次"hello, awk"
awk '{print}' /etc/passwd            //逐条打印/etc/passwd文件
awk '{print "wang"}' /etc/passwd     //每读入/etc/passwd文件一行,打印一次"wang"
awk -F: '{print $1}' /etc/passwd     //打印/etc/passwd文件以":"作为分隔符的第1列
awk -F: '{print $0}' /etc/passwd     //逐条打印/etc/passwd文件
awk -F: '{print $1,$3}' /etc/passwd  //打印以":"作为分隔符的第1列和第3列,以空格作为分隔符输出
awk -F: '{print $1"t"$3}' /etc/passwd    //打印以":"作为分隔符的第1列和第3列,以制表符作为分隔符输出
tail -3 /etc/fstab | awk '{print $2,$4}'  //打印/etc/fstab文件最后3行以空格作为分隔符的第2列和第4列
支持的选项 说明

-f program-file

–file program-file

从文件接收 awk指令,可以同时指定多个文件

-F fs

–field-separator fs

指定(fs)列分隔符

-v var=value

–assign var=value

为 BEGIN 块定义变量var,指定其值为value

-d[file]

–dump-variables[=file]

 

trylife熟知帝国CMS数据结构的用户都知道以前的morepic downpath onlinepath
字段储存是如下:

二、awk变量

 

单行以换行符分割,单项以六个冒号分隔

(一)内置变量

  • FS:输入字段分隔符,默认为空白字符,可以在program中引用
    awk -v FS=':' '{print $1,FS,$3}' /etc/passwd,注意print中的逗号表示1个空格

    • awk变量也可以引用Shell变量,便于脚本编写
      fs=":" ; awk -v FS=$fs '{print $1,FS,$3}' /etc/passwd

图片 1

  • OFS:输出字段分隔符,默认为空白字符
    awk -v FS=':' -v OFS=':' '{print $1,$3,$7}' /etc/passwd

图片 2

  • RS:输入记录分隔符,指定输入时的换行符,原换行符仍有效
    awk -v RS=':' '{print $1}' /etc/passwd

    • 注意到当指定以”:”作为记录分隔符时,输出每条记录的第1个字段时,除了第1条记录外,其他记录的用户名信息都丢失了。

    图片 3

    • 原因在于文件每一行行尾的换行符,当指定其他符号为记录分隔符后,其自身的换行功能得到保留,所以每一行行尾的shell信息和下一行的用户名信息被视作为一条记录,而记录的第一个字段为bash信息,用户名信息没有打印。

图片 4

  • ORS:输出记录分隔符,输出时用指定符号代替换行符
    awk -v RS=':' -v ORS='###' '{print }' /etc/passwd

    • 下图红框的两端内容之间没有”###”分隔,证明属于一条记录,出现的换行证明原文件行尾的换行符功能仍旧保留,再次印证上文所述

    图片 5

  • NF:字段数量

    • awk '{print NF,$0}' /etc/fstab,打印每一行并在行首标明所在行字段数量(以空格为字段分隔符)

    图片 6

    • awk -F: '{print $(NF-1)}' /etc/passwd,打印每行倒数第2个字段(以冒号为字段分隔符)

    图片 7

  • NR:行号

    • awk '{print NR,$0}' /etc/fstab,打印每行的行号

    图片 8

    • awk '{print NR,$0}' /etc/fstab /etc/inittab可以同时打印多个文件,但是行号连续编写

    图片 9

  • FNR:各文件分别计数,行号
    awk '{print FNR,$0}' /etc/fstab /etc/inittab

图片 10

  • FILENAME:当前文件名
    awk '{print FILENAME}' /etc/fstab

图片 11

  • ARGC:命令行参数的个数
    awk 'BEGIN {print ARGC}' /etc/fstab /etc/inittab
    每个红框内容被视作一个参数

    图片 12

  • ARGV:数组,保存的是命令行所给定的各参数
    awk 'BEGIN {print ARGV[0]}' /etc/fstab /etc/inittab
    awk 'BEGIN {print ARGV[1]}' /etc/fstab /etc/inittab
    awk 'BEGIN {print ARGV[2]}' /etc/fstab /etc/inittab

图片 13

  demo,ipaddress俩文件的内容是环网柜、柱上开关柜的主、备ip地址。分别以制表符、冒号分割。

a::::::b::::::c::::::d::::::/r/na2::::::b2::::::c2::::::d2::::::/r/n

(二)自定义变量

  • 自定义变量区分大小写,有两种定义方式

    • -v 选项定义
    • 在program中定义
  • 实验:自定义变量的使用

    • awk -v test='hello, gawk' 'BEGIN{print test}',直接使用v选项定义
    • awk 'BEGIN{test="hello, gawk";print test}',在program中定义

    图片 14

    • awk -F: '{sex="male";print $1,sex,age;age=18}' /etc/passwd
      首行没有第3个字段,因为打印首行第3个字段后才对其变量进行了赋值,之后每一行打印时变量已经赋值,可以正常显示

    图片 15

    • 也可以将program部分写入文件中,使用awk的-f选项导入

echo '{print script,$1,$2}' > awkscript
awk -F: -f awkscript -v script="awk" /etc/passwd

图片 16

$ cat demo
RingNetwork     181.36.1.8      182.36.4.8
Switch          181.32.1.22     182.36.4.42
Switch          181.32.1.23     182.36.4.43
$ cat ipaddress
R:181.36.1.8:182.36.4.8
S:181.32.1.22:182.36.4.42
S:181.32.1.23:182.36.4.43

帝国CMS7.0的多值字段储存则是这样大的

三、printf命令:实现格式化输出

  • 语法:printf “FORMAT”, item1, item2, …

    • 必须指定FORMAT
    • 不会自动换行,需要显式给出换行控制符:n
    • FORMAT中需要分别为后面每个item指定格式符
  • 格式符:与item对应

    • %c:显示字符的ASCII码
    • %d, %i:显示十进制整数
    • %e, %E:显示科学计数法数值
    • %f:显示为浮点数
    • %g, %G:以科学计数法或浮点形式显示数值
    • %s:显示字符串
    • %u:无符号整数
    • %%:显示%自身
  • 修饰符:

    • #[.#]:第一个#控制显示的宽度,第二个#表示小数点后精度,%3.1f
    • -:左对齐(默认右对齐)%-15s
    • +:显示数值的正负符号%+d
  • 实验:printf的使用

    • 显示/etc/passwd文件以冒号为分隔符的第1,3列,并且第1列宽20左对齐,第3列宽10右对齐
      awk -F: '{printf "%-20s %10dn",$1,$3}' /etc/passwd

    图片 17

    • 显示/etc/passwd文件以冒号为分隔符的第1,3列,格式:”Username:
      第1列内容 , ID: 第3列内容”,其中第1列内容宽15左对齐
      awk -F: '{printf "Username: %-15s,ID: %dn",$1,$3}' /etc/passwd

    图片 18

  命令:

单行以六个竖线分割,单项以六个六个冒号分割。

四、操作符

  • 算术操作符:
    x+y, x-y, x*y, x/y, x^y, x%y
    -x: 转换为负数
    +x: 转换为数值

  • 赋值操作符:
    =, +=, -=, *=, /=, %=, ^=
    ++, —

  • 比较操作符:
    ==, !=,>, >=, <, <=

  • 模式匹配符:
    ~:左边是否匹配右边
    !~:左边是否不匹配右边
    示例:
    awk -F: '$0 ~ /root/{print $1}' /etc/passwd
    打印/etc/passwd文件包含”root”内容行的第一个字段(以”:”分隔)
    awk '$0 ~ "^root" ' /etc/passwd
    打印/etc/passwd文件行首为”root”的行
    awk '$0 !~ /root/' /etc/passwd
    打印/etc/passwd文件不包含”root”内容的所有行
    awk -F: '$3==0' /etc/passwd
    打印/etc/passwd文件以”:”分隔的第三个字符等于0的所有行

  • 逻辑操作符:与&&,或||,非!
    示例:
    awk -F: '$3>=0 && $3<1000 {print $1}' /etc/passwd
    打印root用户和系统用户名称(CentOS 7)
    awk -F: '$3==0 || $3>=1000 {print $1}' /etc/passwd
    打印root用户和普通用户的名称(CentOS 7)
    awk -F: '!($3==0){print $1}' /etc/passwd
    打印除root用户外的所有用户名称
    awk -F: '!($3>=500) {print $3}' /etc/passwd
    打印root用户和系统用户的UID(CentOS 6)

  • 函数调用:function_name(argu1, argu2, …)

  • 条件表达式(三目表达式):
    selector?if-true-expression:if-false-expression
    示例4-1:
    awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf "%15s: %-sn",$1,usertype}' /etc/passwd
    打印用户名称,若是普通用户则其后输出”Common User”,否则输出”Sysadmin
    or
    SysUser”,中间以”:”分割。用户名称宽20右对齐,其后的类型信息左对齐(CentOS
    7)

图片 19

    print 
打印输出,参数之间使用逗号分隔。

a::::::b::::::c::::::d::::::||||||a2::::::b2::::::c2::::::d2::::::

五、awk pattern

  • PATTERN:根据pattern条件,过滤匹配的行,再做处理
    • 如果未指定:空模式,匹配每一行

    printf 
输出时,需要指定输出格式。

内容页调用

(一)正则表达式:/regular expression/

仅处理模式匹配到的行,需要用”/ /”括起来

 

?php/* 内容页调用多值字段示例 trylife@diguoCMS.com 20130513 假设字段这个多值字段为tl**/$exp=explode('||||||',$navinfor[tl]);foreach($exp as $k=$v){ /*下一行是分割多值字段的每行中的每项*/ $exp2=explode('::::::',$v); /* $exp2[0] $exp2[1] 以此类推分别是每行的第一个值 第二个值 第三个值 */ echo 'li'.$exp2[0].' '.$exp2[1].'/li';}?

(二)关系表达式:结果为“真”才会被处理

真:结果为非0值,非空字符串
假:结果为空字符串或0值

printf 输出格式铆定符
格式
铆定符
效果说明 例子(页面最下边)
%c 打印成 ascii 码表的“char”形式 2.1
%s 输出字符串 2.2
%d, %i 十进制数的整数部分 2.3
%o 无符号八进制数的整数部分 2.4
%x, %X 同上,大小的区别表示[a-f],[A-F] 2.5
%u 无符号的十进制数的整数部分  
%f 浮点数 2.6
%% 输出%,相当于\输出反斜线一样  
%10s 预留10个字符位置,右对齐  
%-10s 左对齐显示  

(三)行范围

/pat1/,/pat2/:支持使用正则表达式描述,不支持直接给出数字格式

 

(四)BEGIN/END模式

BEGIN{}:仅在开始处理文件中的文本之前执行一次
END{}:仅在文本处理完成之后执行一次

 

示例5-1:pattern中正则表达式和关系表达式的用法

  • awk '/^UUID/{print $1}' /etc/fstab
    打印/etc/fstab文件以UUID开头的行的第1列

图片 20

  • awk '!/^UUID/{print $1}' /etc/fstab
    打印/etc/fastab文件不以UUID开头的行的第1列

  • awk -F: 'i=1;j=1{print i,j}' /etc/passwd
    本条命令是awk -F: 'i=1{print $0};j=1{print i,j}' /etc/passwd的简化,program第1条语句关系判断为真(i=1),故打印本行;第2条语句关系判断为真(j=1),故打印i和j值

图片 21

  • awk '!0' /etc/passwd; awk '!1' /etc/passwd
    打印全部行;一行也不打印

  • awk -F: '$3>=1000{print $1,$3}' /etc/passwd
    打印/etc/passwd文件以”:”为分隔符的第3列数值大于等于1000的行的第1和第3列

  • awk -F: '$3<1000{print $1,$3}' /etc/passwd
    打印/etc/passwd文件以”:”为分隔符的第3列数值小于1000的行的第1和第3列

  • awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd
    打印/etc/passwd文件以”:”为分隔符的最后一列是”/bin/bash”的行的第1列和最后1列

  • awk -F: '$NF~ /bash$/{print $1,$NF}' /etc/passwd
    打印/etc/passwd文件以”:”为分隔符的最后一列是以”bash”作为行尾的行的第1列和最后1列

  • seq 10 | awk 'i=!i'
    读入第1行时,i值取反为1所以打印本行,读入第2行时,i值为1取反后为0所以不打印本行,读入第3行与读入第1行相似,读入第4行与读入第2行相似,以此类推,所以结果为打印奇数行

图片 22

  • seq 10 | awk '!(i=!i)'seq 10 | awk -v i=1 'i=!i'
    与上文类似,结果为打印偶数行

图片 23

  常见变量:

示例5-2:pattern中行范围和BEGIN/END模式的用法

  • awk -F: '/^root>/,/^nobody>/{print $1}' /etc/passwd
    打印/etc/passwd文件从行首是”root”单词的行至行首是”nobody”单词的行中以”:”作为分隔符的第1列

    图片 24

  • awk -F: 'BEGIN{printf "%-8s%sn---------n","USER","UID"}/^root>/,/^sync>/{printf "%-8s%dn",$1,$3}END{print "========="}' /etc/passwd
    BEGIN和END模式适用于打印表头和表尾

图片 25

    FS 
输入列分割符

六、awk action

  • 常用的action分类
    (1) Expressions:算术,比较表达式等
    (2) Control statements:if, while等
    (3) Compound statements:组合语句
    (4) input statements
    (5) output statements:print等

    OFS  输出列分隔符

(一)awk控制语句:if-else

  • 功能:对awk取得的整行或某个字段做条件判断

  • 语法:
    if(condition) {statement;…} [else statement]
    if(condition1) {statement1} else if(condition2){statement2} else
    {statement3}

  • 示例6-1:
    awk -F: '{if($3>=1000)print $1,$3}' /etc/passwd
    打印普通用户名称和UID(CentOS 7)
    awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd
    打印/etc/passwd文件以”:”为分隔符的最后一列是”/bin/bash”的行的第1列
    awk '{if(NF>5) print $0}' /etc/fstab
    打印/etc/fstab文件以空格为分隔符字段数大于5的行
    awk -F: '{if($3>=1000) {printf "Common User: %sn",$1} else {printf "Sysadmin or SysUser: %sn",$1}}' /etc/passwd
    普通用户输出”Common User”,其他用户输出”Sysadmin or
    SysUser”,中间以”:”分割,然后打印用户名称(CentOS 7)
    df| awk -F% '/^/dev/sd/{print $1}'| awk '$NF>=80{print $1,$NF}'
    检查磁盘分区占用率,发现占用率大于等于的分区将分区名称和占用率打印出来
    awk -F: '{if($3>=1000){printf "Common User: %sn",$1} else if($3==0){printf "Sysadmin: %sn",$1} else{printf "SysUser: %sn",$1}}' /etc/passwd
    普通用户输出”Common
    User”,系统用户输出SysUser”,root用户输出”Sysadmin”,中间以”:”分割,然后打印用户名称(CentOS
    7)

图片 26

    RS  输入行分割符

(二)awk控制语句:while循环

  • 功能:条件“真”,进入循环;条件“假”,退出循环

  • 语法:while(condition){statement;…}

  • 示例6-2:

    • awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {print $i,length($i); i++}}' /etc/grub2.cfg
      找出/etc/grub2.cfg文件以不定数量(包含0个)空格作为行首后接字符串”linux16″的行,以空格为分隔符打印这些行每个字段内容和字段长度

    图片 27

    • awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=10) {print $i,length($i)}; i++}}' /etc/grub2.cfg
      找出/etc/grub2.cfg文件以不定数量(包含0个)空格作为行首后接字符串”linux16″的行,以空格为分隔符找出长度大于10的字段,把字段和字段长度打印出来

    图片 28

    ORS  输出行分割符

(三)awk控制语句:do-while循环

  • 功能:无论真假,至少执行一次循环体

  • 语法:do {statement;…}while(condition)

  • 示例6-3:
    awk 'BEGIN{ total=0;i=0;do{ total+=i;i++}while(i<=100);print total}
    从1到100求和

 

(四)awk控制语句:for循环

  • 语法:for(expr1;expr2;expr3) {statement;…}

  • 常见用法:
    for(variable assignment;condition;iterationprocess) {for-body}

  • 特殊用法:能够遍历数组中的元素
    语法:for(var in array) {for-body}

  • 示例6-4:
    awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg
    找出/etc/grub2.cfg文件以不定数量(包含0个)空格作为行首后接字符串”linux16″的行,以空格为分隔符打印这些行每个字段内容和字段长度

图片 29

  • 实验:awk, shell脚本和bc的性能比较
    time awk ‘BEGIN{sum=0;for(i=1;i<=1000000;i++){sum+=i};print
    sum}’
    time (sum=0;for i in {1..1000000};do let sum+=i;done;echo $sum)
    time (sum=0;for ((i=1;i<=1000000;i++));do let sum+=i;done;echo
    $sum)
    time seq -s “+” 1000000 | bc

图片 30

可以看出awk执行效率最高,bc次之,shell脚本的效率最差

    NF  记录数(当前处理的)

(五)awk控制语句:switch, break, continue, next语句

  • switch语句
    语法:switch(expression) {case VALUE1 or /REGEXP/: statement1; case
    VALUE2 or /REGEXP2/: statement2; …; default: statementn}

  • break和continue
    awk ‘BEGIN{sum=0;for(i=1;i<=100;i++)
    {if(i%2==0)continue;sum+=i}print sum}’
    从1至100的奇数求和
    awk ‘BEGIN{sum=0;for(i=1;i<=100;i++) {if(i==66)break;sum+=i}print
    sum}’
    从1至66求和

  • next
    提前结束对本行处理而直接进入下一行处理(awk自身循环)
    awk -F: ‘{if($3%2!=0) next; print $1,$3}’ /etc/passwd
    输出UID为偶数的用户名称和UID

    NR  行数(当前处理)

七、awk数组

 

(一)awk数组的基本用法

  • awk数组均为关联数组:array[index-expression]

  • index-expression格式:
    (1) 可使用任意字符串;字符串要使用双引号括起来
    (2)
    如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”

  • 若要判断数组中是否存在某元素,要使用“index in array”格式进行遍历

  • 示例7-1:

    • awk '{arr[$0]++;print $0,arr[$0]}' password
      输出文件中的每一行,并且输出这是第几次重复本行信息

    图片 31

    • awk '!arr[$0]++' password
      删除重复行,可以对比上图发现前8行中的重复行已经消失。
      解释:当行信息第一次赋值给数组元素时,数组元素值为空,所以取反为真,输出此行;而当相同信息第二、三……次赋值时,数组元素值大于等于1,取反为假,不输出此行,从而实现不输出重复行。

      图片 32

    FNR  行数(当前文件)

(二)awk数组的遍历

  • 若要遍历数组中的每个元素,要使用for循环
    for(var in array) {for-body}
    var会遍历array的每个索引

  • 示例7-2:
    awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for (inx in weekdays) {print weekdays[inx]}}'
    遍历输出weekday数组的值

  • 实验:
    (1)统计处于不同网络状态的tcp连接数

    分析:首先用netstat -tan命令显示tcp连接情况。统计连接数需要考虑问题:第一,如何过滤有效行,可以在awk中的pattern中设置;第二,怎样存储状态名称和累加计数,可以利用awk的关联数组功能,将状态名称作为数组下标,并且数组自加1作为计数器;第三,如何输出每个状态和状态的数量,可以利用for循环的遍历数组功能实现。

    代码实现如下:
    netstat -tan | awk '/^tcp>/{ip[$NF]++}END{for (idx in ip) {print idx,ip[idx]}}'

    图片 33

    (2)统计access_log文件每个ip地址的记录行数,并且输出行数最多的5个ip地址

    分析:查看文件格式,发现ip地址位于行首,并且以空格为分隔符正是第1个字段

    图片 34

    仿照实验(1)的思路,将$1作为数组下标实现统计不同ip的记录数,最后for循环遍历输出每个ip地址和记录行数。之后用sort排序工具按数字倒叙排序,用head工具输出前五行数据

    代码实现如下:
    awk '{ip[$1]++}END{for(idx in ip){print idx,ip[idx]}}' access_log | sort -nr -k2 | head -5

图片 35

 

八、awk函数

 

(一)数值处理:

  • rand():返回0和1之间一个随机数
    awk 'BEGIN{srand();for(i=1;i<=10;i++)print int(rand()*100)}'
    输出10个100以内的随机数,注意使用rand函数前先使用srand函数建立种子

 

(二)字符串处理:

  • length([s]):返回指定字符串的长度

  • sub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并将第一个匹配的内容替换为s
    echo "2008:08:08 08:08:08" | awk 'sub(/:/,"-",$1)'
    将以空格为分隔符的第1个字段搜索到的第1个”:”替换为”-“
    输出结果为”2008-08:08 08:08:08″

  • gsub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并全部替换为s所表示的内容
    echo "2008:08:08 08:08:08" | awk 'gsub(/:/,"-",$1)'
    将以空格为分隔符的第1个字段搜索到的每个”:”替换为”-“
    输出结果为”2008-08-08 08:08:08″

  • split(s,array,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存至array所表示的数组中,第一个索引值为1,第二个索引值为2,…
    netstat -tan | awk '/^tcp>/{split($5,ip,":");count[ip[1]]++}END{for (idx in count){print idx,count[idx]}}'
    netstat -tan输出结果中的Foreign
    Address列ip地址(不含端口号)和其出现次数统计出来,只能使用一次awk命令
    分析:awk实现了以空格为分隔符取Foreign
    Address列字段$5的功能,再使用split函数再次将字段以”:”为分隔符分割。split函数分割的结果存储在数组ip中,而需要之后遍历的信息在数组ip的第一个元素ip[1]中,故将ip[1]再赋值给新的数组count,此后就可以遍历新数组count统计出现次数


(三)自定义函数:

  • 格式:
    function name ( parameter, parameter, … ) {
    statements
    return expression
    }

  • 示例8-1:编写一个函数,实现输出两个变量的较大值
    将函数的实现写在max.awx文件中,执行时导入文件
    文件中代码如下:

function max(var1,var2) {
        var1>var2?maxnum=var1:maxnum=var2
        return maxnum
}
BEGIN {printf " max num is %dn",max(a,b)}

执行命令,awx -f max.awx -v a=5 -v b=3,结果如下

图片 36

 

(四)awk调用shell命令:system()

  • 注意:空格是awk中的字符串连接符,如果system中需要使用awk中的变量可以使用空格分隔,或者说除了awk的变量外其他一律用””引用起来。

  • 示例8-2:

    • awk 'BEGIN{system("hostname") }'
      相当于在shell中执行hostname命令

    • awk 'BEGIN{score=100; system("echo your score is " score) }'
      调用shell命令echo your scre is,然后输出awk的变量score的值

1
输出文本 print

九、awk脚本

  • 可以将awk程序写成脚本,直接调用或执行

    • 注意:当执行awk脚本时,注意需要行首添加#! /bin/awk -f

    • 示例9-1:编写脚本user.awk,实现分行输出普通用户的用户名和UID(CentOS
      7)
      代码如下:

    #! /bin/awk -f
    {if($3>=1000)print $1,$3}
    

    运行脚本前给脚本添加执行权限,执行命令./user.awk -F: /etc/passwd

图片 37

  • 向脚本传递参数

    • 格式:
      awk_script_file var1=value1 var2=value2… Inputfile

    • 注意:在BEGIN过程中不可用。直到首行输入完成以后,变量才可用。可以通过-v
      参数,让awk在执行BEGIN之前得到变量的值。命令行中每一个指定的变量都需要一个-v参数

    • 示例9-2:编写脚本uid.awk,输出指定范围UID号的用户名和其UID
      代码如下:

    #! /bin/awk -f
    {if ($3>=min && $3<=max)print $1,$3}
    

    运行脚本前给脚本添加执行权限,执行命令./uid.awk -F: min=10 max=50 /etc/passwd

    图片 38

1.1
输出指定列信息

  取出每个设备的主ip地址信息

$ awk '{print $2}' demo
181.36.1.8
181.32.1.22
181.32.1.23

 

1.2
列分隔符

1.2.1 列的引用表示

  $1、$2……分别表示当前处理行的第一列、第2列……。$0表示当前行所有列。

$ awk '{print $0}' demo
RingNetwork     181.36.1.8      182.36.4.8
Switch          181.32.1.22     182.36.4.42
Switch          181.32.1.23     182.36.4.43
$ awk '{print $1,$2,$3}' demo
RingNetwork 181.36.1.8 182.36.4.8
Switch 181.32.1.22 182.36.4.42
Switch 181.32.1.23 182.36.4.43

 

  输出awk处理的文件的列数。

$ awk '{print NF}' demo
3
3
3
$ awk '{print NF}' ipaddress
1
1
1
$ awk '{print NF}' demo ipaddress
3
3
3
1
1
1

 

1.2.2
输出列分割符

  awk默认输出分隔符是空格,可以通过变量“OFS”修改,需要使用双引号。

$ awk 'BEGIN{OFS=":"} {print $1,$2,$3}' demo
RingNetwork:181.36.1.8:182.36.4.8
Switch:181.32.1.22:182.36.4.42
Switch:181.32.1.23:182.36.4.43

 

1.2.3 输入列分割符

  awk以空白符作为默认输入分割符,就算分割不是制表符,而是某些个空格符也一样能准确取到主ip。同时,还可以修改默认输入分割符,通过变量“FS”显式指定分割符为空格。

 awk 'BEGIN{FS=":"} {print $1,$2,$3}' ipaddress
R 181.36.1.8 182.36.4.8
S 181.32.1.22 182.36.4.42
S 181.32.1.23 182.36.4.43

   或者在选项“F”里指定分隔符。

$ awk -F: '{print $2}' ipaddress
181.36.1.8
181.32.1.22
181.32.1.23

 

1.3
行分隔符

  输出当前处理的行数

$ awk '{print NR}' demo ipaddress
1
2
3
4
5
6
$ awk '{print FNR}' demo ipaddress
1
2
3
1
2
3

 

2
输出文本 printf

2.1
验证printf命令的%c格式,是把ASCII的Dec列内容转换成Char列内容。(是不是有点像发电报一样)

[root@hp430G2 demo]# cat num
72
101
108
108
111
[root@hp430G2 demo]# awk '{printf("%c", $1)}END{printf("n")}' num
Hello

[root@hp430G2 demo]# cat num
72 101 108 108 111
[root@hp430G2 demo]# awk '{printf("%c%c%c%c%c", $1,$2,$3,$4,$5)}END{printf("n")}' num
Hello

  因为,printf默认不换行,所有要借助END,而且顺便借助不换行完成单词的拼接。而且,模式数量必须与变量数量(列)对应起来。

 

2.2 验证printf命令的%s格式

[root@hp430G2 demo]# cat alpha
Hello
[root@hp430G2 demo]# awk '{printf("%s", $1,$2,$3,$4,$5)}END{printf("n")}' alpha
Hello

 

2.3 验证printf命令的%d、%i格式

[root@hp430G2 mag37]# cat int
3.1415926
[root@hp430G2 mag37]# awk '{printf("%i", $1)}END{printf("n")}' int
3
[root@hp430G2 mag37]# awk '{printf("%d", $1)}END{printf("n")}' int
3

 

2.4 验证printf命令的%o指定输出八进制格式。

[root@hp430G2 mag37]# cat oct
181.37.1.42
182.37.4.42
[root@hp430G2 mag37]# awk -F. '{printf("%o.%o.%o.%on", $1,$2,$3,$4)}' oct
265.45.1.52
266.45.4.52

 

2.5 验证printf命令的%X、%x指定输出十六进制格式,分别输出字母部分的大小写。

[root@hp430G2 mag37]# cat hex
181.37.1.42
182.37.4.42
[root@hp430G2 mag37]# awk -F. '{printf("%x.%x.%x.%xn", $1,$2,$3,$4)}' oct
b5.25.1.2a
b6.25.4.2a
[root@hp430G2 mag37]# awk -F. '{printf("%X.%X.%X.%Xn", $1,$2,$3,$4)}' oct
B5.25.1.2A
B6.25.4.2A

 

2.6
验证%f,没搞明白,这里输出分割符不能成功指定。

[root@hp430G2 mag37]# cat float
181.37 1.42
182.37 4.42
[root@hp430G2 mag37]# awk '{printf("%F %Fn",$1,$2)}' float
181.370000 1.420000
182.370000 4.420000

  可不可以这样看,在使用了printf时,输出控制的权利就完全交割了,变量被失效了。

 

3 数学运算

3.1
算术运算

BEGIN{
r=5
R=r*2
print R
y=R*3.14
print y
}

  支持常见操作符:+ – * / ^ %
=,分别表示加、减、乘、除、次方、取余数、赋值。

**3.2
条件运算**

  支持条件判断:x
< y、x <= y、x > y、x >= y、x == y、x != y、x ~ RE、x !~
RE、&&、||,比较字符串的大小关系、相同关系、匹配正则表达式、多个表达式之间的关系。以及条件表达式:?:

 

3.3
匹配运算

#!/bin/awk -f

$1 ~ /^s/ {print}

  *
注意与上边例子中“print”命令使用“花括号”的位置。

 

4
模式匹配

4.1
逻辑匹配

输出模式匹配的行;首列大于19、在7到11之间、等于12。

awk '$1>19 {print}' demo.txt
awk '$1==12 {print}' demo.txt

 

下边的命令,会使得输出值发生变化;为输出结果重新赋值。

awk '$1=12 {print}' demo.txt

 

4.2
使用正则表达式匹配

使用正则表达式匹配;大写字母后面跟着小写字母、文件大小为2开头、取大小值

awk '/[[:upper:]][[:lower:]]/ {print}' demo.txt
awk '/:..[[:space:]]*2/ {print}' demo.txt
awk '/grep/ {print}' demo.txt

 

4.3
混合模式匹配

找出以两个数字开头、第4列大于40、并且包含一个大写字母后边跟着一个小写字母的行。

awk '/^[[:digit:]]/ && $4>40 && /[[:lower:]]/ {print}' demo.txt
awk '$1>7 && $1<11 {print}' demo.txt

 

4.4
区间模式

awk '/^8/,$4==37 {print}' new.txt

 

4.5
读取数据文件之前的“BEGIN模式”“END”

  由于“begin”块内的命令是在读取文件之前就开始执行的,所以这里的命令不能是操作文件数据的命令。通常可以用来初始化变量。执行顺序就是从“BEGIN”开始,到“模式匹配阶段的数据处理命令”,最后执行“END”。

awk 'BEGIN{print "This is all lines in new.txt."} {print}' new.txt

 

END模块(这里的“BEGIN”、“END”必须是大写的)

awk '{print} END{print "File is over."}' new.txt

 

  在该模式下,awk变量的定义、赋值、引用。

[awk@h p]$ cat demo2.txt
This is for test of awk's begin and end.
[awk@h p]$ cat print.awk
#!/bin/awk -f

BEGIN{
print "begin"
}

{print}

END{
print "endnover"
}
[awk@h p]$ ./print.awk demo2.txt
begin
This is for test of awk's begin and end.
end
over

 

 

3 变量

变量
释义
$0
当前正在处理的记录
$n
第n个字段的值
NF
当前处理记录的字段数
NR
当前已经读入的记录数
FILENAME
正在处理的数据文件的名称
FS
字段分割符(默认空格、或制表符)
RS
记录分割符(默认换行)

 

  NF表示字段数,更有用的可以得到最后一个字段(当每行不同字段时更有用)。可以获取文件名、文件大小

[root@Rsync logs4developers]# tree -fh | grep "M" | awk '{print $NF ,$(NF-1)}'

3.1
普通变量

[awk@h p]$ cat demo1.awk
#!/bin/awk -f

BEGIN{
age=33
say_hello="hello"
print age
print say_hello
[awk@h p]$ awk -f demo1.awk
33
hello

 

3.2
内置变量

[awk@h p]$ cat ip_port.txt
172.17.36.40:22,3306
10.134.1.4:22,1521
[awk@h p]$ awk 'BEGIN{FS=":"; RS="n"; RS=""; ip="ip = "; port="   port = "} {print ip $1 port $2}' ip_port.txt
ip = 172.17.36.40   port = 22,3306
ip = 10.134.1.4   port = 22,1521

 

4 使用脚本

4.1 在脚本中执行
awk 命令

[web@h p]$ cat my_awk.sh
#!/bin/awk -f

{print}
[web@h p]$ ./my_awk.sh demo.txt

 

4.2
交互模式下的“文件结束符”

运行这个脚本

#!/bin/awk -f

BEGIN{
exitpro="press <ctrl+d> exit the script."
print "test is beginning."
print exitpro
print "============================="
}

{print}

END{
print "============================="
print "test is over."
}

  脚本运行后,终端等待输入内容,输入结束时需要给脚本文件发送“EOF”信号。按组合键“ctrl+d”退出(Windows平台“ctrl+z”)。

 

4.3
体会命令执行模式

运行这个脚本

#!/bin/awk -f

{
print
print "Have two print."
}

 

  当命令“print”没有“file“时,以交互模式执行;执行时这里也是需要“EOF”的,第一条命令执行结束后,执行下一条命令;但是“打印”命令始终是需要一个“EOF”的,而这个信号的接收不会影响后边命令的执行。

 

  看到上边的例子,我会以为“需要在EOF是因为有个命令的缘故”。去掉脚本中的“print”命令,结果发现依然需要。不同之处在于没有回显。

  在脚本执行时,添加一个“demo.txt”。发现脚本依然可以执行,说明
awk 在执行时,“pattern”、“actions”都可以不需要。

 

4.4
命令的执行顺序

  awk处理“file”时,按照“记录”依次处理。其中的命令执行是每条命令执行完读入的一条“记录”下一条命令接着处理同样一条“记录”。

[awk@h p]$ cat demo.txt
This is row1.
This is row2.
This is row3.
[awk@h p]$ cat print-file.awk
#!/bin/awk -f

{
print
print
}
[awk@h p]$ 
This is row1.
This is row1.
This is row2.
This is row2.
This is row3.
This is row3.

 

6 函数

6.1
字符串函数

 

函数 释义
index(s1,s2) 返回 s2 在 s1 中的位置;返回值从“1”开始,“0”代表不存在
length(s1) 返回字符串的长度;返回整数值
match(s1,RE) 查找匹配正则表达式匹配的字符串;涉及变量“RSTART”,“RLENGTH”
split(s1,array,sep) 以“sep”分割“s1”后,返回“array”

 

[awk@h p]$ awk 'add=index($0,"sunny") {print add}' demo.txt
1
[awk@h p]$ awk '{print index($0,"sunny")}' demo.txt
1
0

 

 6.2
算术函数

函数 释义
int(x) 返回整数部分
rand() 反馈0~1之间的随机数
srand([x]) 反回一个基于“x”的随机数

 

7 数组

7.1
数组的定义与引用

#!/bin/awk -f

BEGIN{
port[1]=22
port[2]=3389
port[3]=10022

print port[1],port[2],port[3]
}

 

7.2
数组遍历

借用“for
循环”遍历数组元素

 

8 流程控制

 

 

 

9 格式化输出

 

 

 

10 shell交互

 

You can leave a response, or trackback from your own site.

Leave a Reply

网站地图xml地图