AWK再次认识--内置的参数,以及编写脚本

原本这是篇给公司内同事写的培训文章,对于初学awk的人还蛮有帮助,贴到这里与大家共享一下。

〇、前言

    意见反馈,请mailto:datouwang@gmail.com。

 

一、AWK简介

         AWK名字来源于三位创造者Aho、Weinberger和Kernighan统称。

         AWK擅长处理文本数据。

 

二、AWK的调用方式

         awk [-Ffs] [-v var=value] [program | -f progfile ...] [file ...]

 

    1、命令行方式

         例如:

        

awk '{print $1}' file

ps -ef|grep program|awk '{print $2}'

 

 

         2、文件方式

         例如:

awk -f progfile file

 

        

         3、文件解释器方式

         AWK脚本文件开头需要注明调用方式,典型写法为:

         #!/bin/awk -f

    注意-f后面有空格。

         脚本文件需要有执行权限,如果没有需要使用chmod +x progfile赋权。

         例如:

progfile file

 

三、AWK参数

         -F  指定域分隔符,例如:-F "|",即以|作为域分隔符,默认分隔符为一个或多个空格或TAB,即"[[:space:]][[:space:]]*"。

         -v  定义变量,从shell给awk传递变量,如-vDATE=$DATE,即将shell中$DATE变量值传递给awk变量DATE。

         -f  指定脚本文件,例如-f progfile。

 

四、AWK内置变量

         FS      域分隔符

         NF      域个数

         NR      行数

         FNR     同上

         FILENAME    处理的文件名,当输入为管道时,FILENAME为空。

         RS      行分隔符

         OFS     输出域分隔符

         ORS     输出行分隔符

         OFMT        数字输出格式

         CONVFMT     数字内部转换格式

         SUBSEP      多维数组索引分隔符

         ARGC        输入参数个数

         ARGV        输入参数数组

         ENVIRON     环境变量数组

         RSTART      match()函数正则匹配到字符串开始位置

         RLENGTH     match()函数正则匹配到字符串的长度

 

五、AWK内置函数

         blength[([s])]          计算字符串长度(byte为单位)

    length[([s])]           计算字符串长度(character为单位)

    rand()              生成随机数

         srand([expr])           设置rand() seed

    int(x)              字符串转换为整型

         substr(s, m [, n])      取子字符串

         index(s, t)         在字符串s中定位t字符串首次出现的位置

         match(s, ere)           在字符串s中匹配正则ere,match修改RSTART、RLENGTH变量。

         split(s, a[, fs])       将字符串分割到数组中

         sub(ere, repl [, in])   字符串替换

         gsub                同上

         sprintf(fmt, expr, ...) 拼字符串

         system(cmd)         在shell中执行cmd。

         toupper(s)          字符串转换为大写

         tolower(s)          字符串转换为小写

 

 

六、AWK流程控制

         if(expression) statement [ else statement ]

    while(expression) statement

    for(expression;expression;expression) statement

    for(var in array) statement

    do statement while(expression)

    break

    continue

    {[statement  ...]}

    expression          # commonly  var = expression

    print [expression-list] [ > expression]

    printf format [, expression-list] [ > expression]

    return [expression]

    next                # skip remaining patterns on this input line.

    delete array [expression]   # delete an array element.

    exit [expression]   # exit immediately; status is expression.

 

七、AWK简单应用范例

         AWK脚本分为三部分BEGIN段,处理段,END段。其中BEGIN段在第一行读取之前执行,END段在最后一行处理后执行。

 

1、内容过滤,同"grep tag file"。

#前两个语句为正则匹配

 

awk '/tag/ {print}' file

awk '{if($0 ~/tag/) print}' file

awk '{if(index($0, "tag") > 0) print}' file

 

 

2、取特定列,同"cut –f1 –f3 –f5 file"。

#输出文件第1、3、5列

 

awk '{print $1, $3, $5}' file

 

        

3、对文件内容进行剔重,类似"sort -u file",但未排序。

#如果当前行未存在于rec HASH表中,则记录此行数据,并输出

 

awk '{if(!($0 in rec)) {rec[$0]=1; print $0;}}' file

 

         AWK中数组有两种用法普通数组和HASH数组,此处为HASH数组。

        

 

4、仅输出数据

#输出100行数据

 

awk ‘BEGIN {for(i = 0; i < 100; i++) printf("this is %d\n", i);}’

 

可见,如果脚本中只有BEGIN段,可以没有输入。

 

5、统计数据

#对第一列和第二列数据进行汇总,最终输出

 

awk ‘{a+=$1; b+=$2}END{printf("a=%d\n,b=%d\n", a, b);}’ file

 

 

 

八、AWK高级应用范例

 

1、 分组功能,类似Group by功能

#使用第一列作为分组列,第二列为聚合列,即select col1, sum(col2) from file group by col1

 

awk ‘{tot[$1] += $2}END{for(i in tot) printf("%s %d\n", i, tot[i]);}’ file

 

#比上个例子增加一个类似having的用法

 

awk ‘{tot[$1] += $2}END{for(i in tot) if(tot[i] > 10) printf("%s %d\n", i, tot[i]);}’ file

 

#使用第一列作为分组列,第二列、第三列为聚合列

 

awk ‘{tot1[$1] += $2; tot2[$1] += $3;}END{for(i in tot1) printf("%s %d %d\n", i, tot1[i], tot2[i]);}’ file

 

#多维数组例子,可将多个字段作为分组列,AWK使用一维数组模拟多维数组,使用\034作为分隔符

 

awk ‘{tot1[$1, $2] += $3; tot2[$1, $2] += $4;}END{for(i in tot1) printf("%s %d %d\n", i, tot1[i], tot2[i]);}’ file 

 

 

 

2、 文件操作

#将两个文件根据filename1的第一列和filename2的第二列进行关联

 

BEGIN {

        #读取filename1文件内容

        while((getline < "filename1") != NULL)

        {

                rel[$1] = 1;

                rec1[$1] = $2;

        }

 

        while((getline < "filename2") != NULL)

        {

                rel[$2] = 1;

                rec2[$2] = $3;

        }

 

        for(i in rel)

        {

                printf("%s %s %s\n", i, rec1[i], rec2[i]);

        }

}

 

#将文件按照字段进行拆分

 

{

        print $0 >> "split/" substr($1,1,7);

}

 

 

3、 从SHELL向AWK传递变量

awk  -vAWK_DATE=$DATE 'BEGIN {print AWK_DATE}'

 

 

4、 在AWK内部读取shell命令输出

#读取ls命令输出,在AWK中打印输出

 

BEGIN {

        while("ls"|getline)

        {

                print $0;

        }

}

 

#读取date输出

 

BEGIN {

        "date" | getline;

 

        print $0;

 

        "date +%Y" | getline v_year;

 

        print v_year;

}

 

 

 

5、 将AWK输出通过管道传递给SHELL命令

#将打印信息输出给sort进行排序

 

BEGIN {

        for(i = 0; i < 100; i++)

        {

                printf("%03d\n", 100 - i) | "sort";

        }

}

 

 

6、 正则表达式简单例子

#演示正则表达式的使用方法

 

BEGIN {

        str1 = "abc.123@gmail.com";

        str2 = "123123abcd@gmail.com";

        str3 = "&^%76123@gmail.com";

        str4 = "zxcvb@sohu.com.cn.1231231";

 

        match(str1, "[a-zA-Z][a-zA-Z0-9.]*@[a-zA-Z0-9][a-zA-Z0-9.]*.[a-zA-Z]*[a-zA-Z]");

 

        if(RSTART > 0)

                printf("%s\n", substr(str1, RSTART, RLENGTH));

        else

                printf("[%s] not match\n", str1);

 

        match(str2, "[a-zA-Z][a-zA-Z0-9.]*@[a-zA-Z0-9][a-zA-Z0-9.]*.[a-zA-Z]*[a-zA-Z]");

 

        if(RSTART > 0)

                printf("%s\n", substr(str2, RSTART, RLENGTH));

        else

                printf("[%s] not match\n", str2);

 

        match(str3, "[a-zA-Z][a-zA-Z0-9.]*@[a-zA-Z0-9][a-zA-Z0-9.]*.[a-zA-Z]*[a-zA-Z]");

 

        if(RSTART > 0)

                printf("%s\n", substr(str3, RSTART, RLENGTH));

        else

                printf("[%s] not match\n", str3);

 

        match(str4, "[a-zA-Z][a-zA-Z0-9.]*@[a-zA-Z0-9][a-zA-Z0-9.]*.[a-zA-Z]*[a-zA-Z]");

 

        if(RSTART > 0)

                printf("%s\n", substr(str4, RSTART, RLENGTH));

        else

                printf("[%s] not match\n", str4);

 

 

}

 

 

7、自定义函数

function my_plus(a, b)

{

        return a + b;

}

BEGIN {

        printf("%d\n", my_plus(123, 321));

}

 

 

九、一些应用范例

         1、验证话单正确性的一个脚本

/^vc/ {

        #取话单中各个变量

        call_type = substr($0,3,2);

        call_duration = int(substr($0,95,6));

        roam_type = substr($0,210,1);

        fee_type = substr($0,211,1);

        dial_type = substr($0,212,3);

        chat_type = substr($0,215,3);

 

        cfee = int(substr($0,218,9));

        lfee = int(substr($0,236,9));

 

        #如果为国际漫游,不分析,跳过

        if(roam_type > 4)

        {

                next;

        }

 

        if(call_type == "01")

        {

                if(substr(dial_type,1,1) != "0")

                {

                        if(lfee > 0)

                        {

                                printf("%s:LFEE_01\n", $0);

                        }

 

                        next;

                }

 

                if(roam_type != "0")

                {

                        if(fee_type == "0" || fee_type == "2" || fee_type == "3")

                        {

                                if(lfee > 0)

                                {

                                        printf("%s:LFEE_ERR02\n", $0)

                                }

                        }

                        else

                        {

                                if(cfee > 0)

                                {

                                        printf("%s:CFEE_ERR01\n", $0);

                                }

                        }

                }

                else

                {

                        if(fee_type != "0")

                        {

                                if(cfee > 0)

                                {

                                        printf("%s:CFEE_ERR02\n", $0);

                                }

                        }

                }

        }

 

        if(call_type == "02")

        {

                if(lfee > 0)

                {

                        printf("%s:LFEE_ERR03\n", $0);

                }

        }

}

 

         2、一个模拟求取批价标批费率计划的例子

function my_match(str, pat)

{

#for debug

#printf("str==>|%s|,pat==>|%s|\n", str, pat);

 

        if(pat == "*")

                return 1;

 

        n = split(pat, arr, ",");

 

        for(z = 1; z <= n; z++)

        {

                gsub("\?", "[a-zA-Z0-9]", arr[z]);

 

#for debug

#printf("str==|%s|,arr==>|%s|\n", str, arr[z]);

               

                match(str, arr[z]);

                if(RSTART > 0)

                {

                        return 1;

                }

        }

 

        return 0;

       

}

 

BEGIN {

 

        dial_cnt = 0;

        while((getline < "dial.lst") != NULL)

        {

                dial[dial_cnt] = $1;

 

                dial_cnt++;

        }

 

        chat_cnt = 0;

        while((getline < "chat.lst") != NULL)

        {

                chat[chat_cnt] = $1;

 

                chat_cnt++;

        }

 

        cfg_cnt = 0;

 

        while((getline < "plan.lst") != NULL)

        {

                cfg_dial[cfg_cnt] = $1;

                cfg_chat[cfg_cnt] = $2;

                cfg_item[cfg_cnt] = $3;

                cfg_plan[cfg_cnt] = $4;

 

                cfg_cnt++;

        }

 

        for(d = 0; d < dial_cnt; d++)

        {

                for(c = 0; c < chat_cnt; c++)

                {

                        printf("%s %s|", dial[d], chat[c]);

                       

                        out_cnt = 0;

                        

                        for(i = 0; i < cfg_cnt; i++)

                        {

#for debug

#printf("\n<%d,%d,%d>test match==>|<%s, %s>; <%s, %s>|\n", d, c, i, dial[d], cfg_dial[i], chat[c], cfg_chat[i]);

 

                                if(my_match(dial[d], cfg_dial[i]) == 1 && my_match(chat[c], cfg_chat[i]) == 1)

                                {

                                        if(out_cnt == 0)

                                        {

                                                printf("%s %s %s %s\n", cfg_item[i], cfg_plan[i], cfg_dial[i], cfg_chat[i]);

                                        }

                                        else

                                        {

                                                printf("%s %s|%s %s %s %s\n", dial[d], chat[c], cfg_item[i], cfg_plan[i], cfg_dial[i], cfg_chat[i]);

                                        }

                                               

                                        out_cnt++;

                                }

                        }

                       

                        if(out_cnt == 0)

                        {

                                printf("NULL\n");

                        }

                }

        }

}

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/445022.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AWk高级编程

首先再说一说awk的工作流程还是有必要的 : 执行awk时, 它会反复进行下列四步骤. 1. 自动从指定的数据文件中读取一个数据行. 2. 自动更新(Update)相关的内建变量之值. 如 : NF, NR, $0... 3. 依次执行程序中所有 的 Pattern { Actions } 指令. 4. 当执行完程序中所有 Pattern {…

leetcode19. 删除链表的倒数第N个节点

给定一个链表&#xff0c;删除链表的倒数第 n 个节点&#xff0c;并且返回链表的头结点。 示例&#xff1a; 给定一个链表: 1->2->3->4->5, 和 n 2. 当删除了倒数第二个节点后&#xff0c;链表变为 1->2->3->5. 说明&#xff1a; 给定的 n 保证是有效…

python模块(5)-Matplotlib 简易使用教程

Matplotlib简易使用教程0.matplotlib的安装1.导入相关库2.画布初始化2.1 隐式创建2.2 显示创建2.3 设置画布大小2.4 plt.figure()常用参数3.plt. 能够绘制图像类型3.1等高线3.2 箭头arrow4.简单绘制小demodemo1.曲线图demo2-柱状、饼状、曲线子图5.plt.plot()--设置曲线颜色,粗…

random_shuffle 和transform算法

1)STL中的函数random_shuffle()用来对一个元素序列进行重新排序(随机的),函数原型如下: std::random_shuffle

C语言字符输出格式化

符号属性 长度属性 基本型 所占 位数 取值范围 输入符举例 输出符举例 -- -- char 8 -2^7 ~ 2^7-1 %c %c、%d、%u signed -- char 8 -2^7 ~ 2^7-1 %c %c、%d、%u unsigned -- char 8 0 ~ 2^8-1 %c %c、%d、%u [signed] short [int] 16 -2^15 ~ 2^15-1 %hd %hd unsigned short […

leetcode20 有效的括号

给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串&#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 注意空字符串可被认为是有效字符串。 示…

python模块(6)-Pandas 简易使用教程

Pandas 简易教程1.Pandas简介2.创建2.1创建dataFrame2.2创建Series3.dataframe数据访问3.1 获取一列--列标签3.2 获取多列--列标签列表3.3 获取一行--行标签.loc()3.4 获取多行--行切片操作.loc()3.5 index 获取行列信息--df.iloc()3.6 获取一个元素3.7 布尔值选择数据4.datafr…

windows 如何查看端口占用情况?

开始--运行--cmd 进入命令提示符 输入netstat -ano 即可看到所有连接的PID 之后在任务管理器中找到这个PID所对应的程序如果任务管理器中没有PID这一项,可以在任务管理器中选"查看"-"选择列" 经常,我们在启动应用的时候发现系统需要的端口被别的…

泛型lua的for循环以及lua的特殊的dowhile循环

范型for循环&#xff1a; -- print all values of array a a{1,2,3,4,5,6,7}; for i,v in ipairs(a) do print(v) end 范型for遍历迭代子函数返回的每一个值。 再看一个遍历表key的例子&#xff1a; -- print all keys of table t map {["gaoke"]1,["gaoxin&…

leetcode1 两数之和

给定一个整数数组 nums 和一个目标值 target&#xff0c;请你在该数组中找出和为目标值的那 两个 整数&#xff0c;并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;你不能重复利用这个数组中同样的元素。 示例: 给定 nums [2, 7, 11, 15], t…

Linux(5)-用户/权限-adduser,su,chmod

用户、权限管理1. adduserstep1: 添加新用户step2: 赋予sudo权限。step3: 删除用户2. useradd &#xff08;建议不要使用&#xff09;3. 切换用户su4. 查看系统中所有用户5. 修改用户对路径/文件的读写权限1. adduser step1: 添加新用户 sudo adduser username 按照提示输入新…

网络游戏服务器架构

网络游戏一般采用C/S结构&#xff0c;客户端负责绘制游戏世界的实时画面&#xff0c;服务器端则负责响应所有客户端的连接请求和游戏逻辑处理&#xff0c;并控制所有客户端的画面绘制&#xff0c;客户端与服务器通过网络数据包交互完成每一步游戏逻辑。 网关服务器方式&#x…

leetcode3 无重复字符最长子串

给定一个字符串&#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc"&#xff0c;所以其长度为 3。 示例 2: 输入: "bbbbb" 输出: 1 解释: 因为无重复字符…

如何正确编写linux守护进程

1、守护进程&#xff0c;也就是通常说的Daemon进程&#xff0c;是Linux中的后台服务进程。它是一个生存期较长的进程&#xff0c;通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。如果想让某个进程不因为用户或终端或其他地变化而受到影响&#xff0c;那…

Linux(6)-命令行的使用,history,shell脚本

命令行的使用,shell脚本1.终端shell,man1.1 Ctrlr--匹配查找历史命令1.2 history [n] --列出历史命令1.3&#xff01;--执行历史命令2.shell 编程2.1 shell脚本2.2 注释2.3 指明所用的shell2.4 支持函数2.5 使用变量2.6 解析命令行参数2.7 if, for, case, while2.8 shell脚本中…

lua元表的理解

元表概念 &#xff08; Metatable&#xff09;元表由键名为 事件 (event) 和其中的值叫作元方法 (metamethod)组成。在lua中每个值都有一个元表。而table和userdata所定义的值允许自定义对应的元表&#xff0c;其他都是用统一的元表。我的理解&#xff0c;元表&#xff0c;其实…

程序以及论文

本人长期承接大学计算机专业的毕业设计和论文的编写。 主要开发语言C&#xff0c;C &#xff08;windows或linux平台皆可&#xff09;&#xff0c;php&#xff0c;c#&#xff0c;VC 。 课题内容可以是 管理系统&#xff0c;可以是 网站设计开发 可以是 网络聊天 可以是 应用…

Github(1)-概览,初始化仓库

Github网页-本地git1.github网页1.1 主要界面1.1.1github主页1.1.2仓库主页1.1.3 个人页面1.2 注册github账号1.3 新建平台仓库2.git-本地仓库2.1 git本地仓库的三个区域2.2 创建一个本地仓库GitHub 本质上是一个代码托管平台&#xff0c;它提供的是基于 Git 的代码托管服务。G…

Lua 协程

Lua里的协程是一个原来没见过的东西&#xff0c;Python的Gevent也是一个基于coroutine的python网络开发框架。性能据说很不错。协同的一个关键特征是它可以不断颠倒调用者与被调用者之间的关系协程和一般多线程的区别是&#xff0c;一般多线程由系统决定该哪个线程执行&#xf…

leetcode16 最接近的三数之和

给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数&#xff0c;使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。 例如&#xff0c;给定数组 nums [-1&#xff0c;2&#xff0c;1&#xff0c;-4], 和 target 1…