news 2026/8/29 5:38:39

Linux 三剑客 - Awk 命令指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux 三剑客 - Awk 命令指南

本文取自 Linux 中国,本人仅是对文章做一个防丢备份。

摘要:Awk 是一种小巧的编程语言及命令行工具,适合服务器日志处理。本文介绍其代码结构(模式与行为)、数据类型、三大类模式、域、常用行为、函数及特殊变量,并通过处理 Erlang 崩溃转储文件的示例展示实际应用。

1、什么是 Awk

Awk 是一种小巧的编程语言及命令行工具。(其名称得自于它的创始人 Alfred Aho、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母)。它非常适合服务器上的日志处理,主要是因为 Awk 可以对文件进行操作,通常以可读文本构建行。

我说它适用于服务器是因为日志文件,转储文件(dump files),或者任意文本格式的服务器终止转储到磁盘都会变得很大,并且在每个服务器你都会拥有大量的这类文件。如果你经历过这样的情境——在没有像Splunk1或者其他等价的工具情况下不得不在50个不同的服务器里分析几G的文件,你会觉得去获取和下载所有的这些文件并分析他们是一件很糟糕的事。

我亲身经历过这种情境。当一些 Erlang 节点将要死掉并留下一个 700MB 到 4GB 的崩溃转储文件(crash dump)2时,或者当我需要在一个小的个人服务器(叫做 VPS)上快速浏览日志,查找一个常规模式时。

在任何情况下,Awk都不仅仅只是用来查找数据的(否则,grep 或者 ack 已经足够使用了)——它同样使你能够处理数据并转换数据。

2、代码结构

Awk 脚本的代码结构很简单,就是一系列的模式(pattern)和行为(action):

# commentPattern1{ACTIONS;}# commentPattern2{ACTIONS;}# commentPattern3{ACTIONS;}# commentPattern4{ACTIONS;}

扫描文档的每一行时都必须与每一个模式进行匹配比较,而且一次只匹配一个模式。那么,如果我给出一个包含以下内容的文件:

this is line1this is line2

this is line 1 这行就会与 Pattern1 进行匹配。如果匹配成功,就会执行 ACTIONS。然后 this is line 1 会和 Pattern2 进行匹配。如果匹配失败,它就会跳到 Pattern3 进行匹配,以此类推。

一旦所有的模式都匹配过了,this is line 2 就会以同样的步骤进行匹配。其他的行也一样,直到读取完整个文件。

简而言之,这就是 Awk 的运行模式

3、数据类型

Awk 仅有两个主要的数据类型:字符串和数字。即便如此,Awk 的字符串和数字还可以相互转换。字符串能够被解释为数字并把它的值转换为数字值。如果字符串不包含数字,它就被转换为 0。

它们都可以在你代码里的 ACTIONS 部分使用 = 操作符给变量赋值。我们可以在任意时刻、任意地方声明和使用变量,也可以使用未初始化的变量,此时他们的默认值是空字符串:“”。

最后,Awk 有数组类型,并且它们是动态的一维关联数组。它们的语法是这样的:var[key] = value 。Awk 可以模拟多维数组3,但无论怎样,这是一个大的技巧(big hack)。

4、模式

可以使用的模式分为三大类:正则表达式、布尔表达式和特殊模式。

正则表达式和布尔表达式

你使用的 Awk 正则表达式比较轻量。它们不是 Awk 下的 PCRE(但是 gawk 可以支持该库——这依赖于具体的实现!请使用awk –version查看),然而,对于大部分的使用需求已经足够了:

/admin/{...}# any line that contains 'admin'/^admin/{...}# lines that begin with 'admin'/admin$/{...}# lines that end with 'admin'/^[0-9.]+ /{...}# lines beginning with series of numbers and periods/(POST|PUT|DELETE)/# lines that contain specific HTTP verbs

注意,模式不能捕获4特定的组(groups)使它们在代码的 ACTIONS 部分执行。模式是专门匹配内容的。

布尔表达式与 PHP 或者 Javascript 中的布尔表达式类似。特别的是,在 awk 中可以使用&&(“与”)、||(“或”)、!(“非”)操作符。你几乎可以在所有类 C语言中找到它们的踪迹。它们可以对常规数据进行操作。

与 PHP 和 Javascript 更相似的特性是比较操作符。== 操作符会进行模糊匹配(fuzzy matching),因此 “23” 字符串等于 23,“23” == 23 表达式返回 true。!= 操作符同样在 awk 里使用,并且别忘了其他常见的操作符:>,<,>=,和<=

你同样可以混合使用它们:布尔表达式可以和常规表达式一起使用。/admin/ || debug == true这种用法是合法的,并且在遇到包含 “admin” 单词的行或者 debug 变量等于 true 时该表达式就会匹配成功。

注意,如果你有一个特定的字符串或者变量要与正则表达式进行匹配,~ 和!~ 就是你想要的操作符。 这样使用它们:string ~ /regex/string !~ /regex/

同样要注意的是,所有的模式都只是可选的。一个包含以下内容的 Awk 脚本:

{ ACTIONS }

对输入的每一行都将会简单地执行 ACTIONS。

5、特殊的模式

在 Awk 里有一些特殊的模式,但不是很多。

第一个是 BEGIN,它仅在所有的行都输入到文件之前进行匹配。这是你可以初始化你的脚本变量和所有种类的状态的主要地方。

另外一个就是 END。就像你可能已经猜到的,它会在所有的输入都被处理完后进行匹配。这使你可以在退出前进行清除工作和一些最后的输出。

最后一类模式,要把它进行归类有点困难。它处于变量和特殊值之间,我们通常称它们为域(Field)。而且名副其实。

6、域

使用直观的例子能更好地解释域:

# According to the following line## $1 $2 $3# 00:34:23 GET /foo/bar.html# _____________ _____________/# $0# Hack attempt?/admin.html$/&&$2=="DELETE"{print"Hacker Alert!";}

域(默认地)由空格分隔。$0 域代表了一整行的字符串。 $1 域是第一块字符串(在任何空格之前), $2 域是后一块,以此类推。

一个有趣的事实(并且是在大多是情况下我们要避免的事情),你可以通过给相应的域赋值来修改相应的行。例如,如果你在一个块里执行$0 = “HAHA THE LINE IS GONE”,那么现在下一个模式将会对修改后的行进行操作而不是操作原始的行。其他的域变量都类似。

7、行为

这里有一堆可用的行为(possible actions),但是最常用和最有用的行为(以我的经验来说)是:

{print$0;}# prints $0. In this case, equivalent to 'print' alone{exit;}# ends the program{next;}# skips to the next line of input{a=$1;b=$0}# variable assignment{c[$1]=$2}# variable assignment (array){if(BOOLEAN){ACTION}elseif(BOOLEAN){ACTION}else{ACTION}}{for(i=1;i<x;i++){ACTION}}{for(iteminc){ACTION}}

这些内容将会成为你的 Awk 工具箱的主要工具,在你处理日志之类的文件时你可以随意地使用它们。

Awk 里的变量都是全局变量。无论你在给定的块里定义什么变量,它对其他的块都是可见的,甚至是对每一行都是可见的。这严重限制了你的Awk脚本大小,不然他们会造成不可维护的可怕结果。请编写尽可能小的脚本。

8、函数

可以使用下面的语法来调用函数:

{somecall($2)}

这里有一些有限的内置函数可以使用,所以我可以给出这些函数的通用文档(regular documentation)5。

用户定义的函数同样很简单:

# function arguments are call-by-valuefunctionname(parameter-list){ACTIONS;# same actions as usual}# return is a valid keywordfunctionadd1(val){returnval+1;}

9、特殊变量

除了常规变量(全局的,可以在任意地方使用),这里还有一系列特殊的变量,它们的的作用有点像配置条目(configuration entries):

BEGIN{# Can be modified by the userFS=",";# Field SeparatorRS="n";# Record Separator (lines)OFS=" ";# Output Field SeparatorORS="n";# Output Record Separator (lines)}{# Can't be modified by the userNF# Number of Fields in the current Record (line)NR# Number of Records seen so farARGV / ARGC# Script Arguments}

我把可修改的变量放在 BEGIN 里,因为我更喜欢在那重写它们。但是这些变量的重写可以放在脚本的任意地方然后在后面的行里生效。

10、示例

以上的就是 Awk 语言的核心内容。我这里没有大量的例子,因为我趋向于使用 Awk 来完成快速的一次性任务。

不过我依然有一些随身携带的脚本文件,用来处理一些事情和测试。我最喜欢的一个脚本是用来处理 Erlang 的崩溃转储文件,形如下面的:

=erl_crash_dump:0.3 Tue Nov1802:52:442014Slogan: init terminatingindo_boot()System version: Erlang/OTP17[erts-6.2][source][64-bit][smp:8:8][async-threads:10][hipe][kernel-poll:false]Compiled: Fri Sep1903:23:192014Taints: Atoms:12167=memory total:19012936processes:4327912processes_used:4319928system:14685024atom:339441atom_used:331087binary:1367680code:8384804ets:382552=hash_table:atom_tab size:9643used:6949...=allocator:instr option m:falseoption s:falseoption t:false=proc:<0.0.0>State: Running Name: init Spawned as: otp_ring0:start/2 Run queue:0Spawned by:[]Started: Tue Nov1802:52:352014Message queue length:0Number of heap fragments:0Heap fragment data:0Link list:[<0.3.0>,<0.7.0>,<0.6.0>]Reductions:29265Stack+heap:1598OldHeap:610Heap unused:656OldHeap unused:468Memory:18584Program counter: 0x00007f42f9566200(init:boot_loop/2 +64)CP: 0x0000000000000000(invalid)=proc:<0.3.0>State: Waiting...=port:#Port<0.0>Slot:0Connected:<0.3.0>Links:<0.3.0>Port controls linked-in driver: efile=port:#Port<0.14>Slot:112Connected:<0.3.0>...

产生下面的结果:

$awk-fqueue_fun.awk$PATH_TO_DUMPMESSAGE QUEUE LENGTH: CURRENT FUNCTION======================================10641: io:wait_io_mon_reply/212646: io:wait_io_mon_reply/232991: io:wait_io_mon_reply/22183837: io:wait_io_mon_reply/2730790: io:wait_io_mon_reply/280194: io:wait_io_mon_reply/2...

这是在Erlang进程里运行的函数列表,它们导致了 mailboxe 变得很庞大。脚本6在这:

# Parse Erlang Crash Dumps and correlate mailbox size to the currently running# function.## Once in the procs section of the dump, all processes are displayed with# =proc:<0.M.N> followed by a list of their attributes, which include the# message queue length and the program counter (what code is currently# executing).## Run as:## $ awk -v threshold=$THRESHOLD -f queue_fun.awk $CRASHDUMP## Where $THRESHOLD is the smallest mailbox you want inspects. Default value# is 1000.BEGIN{if(threshold==""){threshold=1000# default mailbox size}procs=0# are we in the =procs entries?print"MESSAGE QUEUE LENGTH: CURRENT FUNCTION"print"======================================"}# Only bother with the =proc: entries. Anything else is useless.procs==0&&/^=proc/{procs=1}# entering the =procs entriesprocs==1&&/^=/&&!/^=proc/{exit0}# we're done# Message queue length: 1210# 1 2 3 4/^Message queue length: /&&$4>=threshold{flag=1;ct=$4}/^Message queue length: /&&$4<threshold{flag=0}# Program counter: 0x00007f5fb8cb2238 (io:wait_io_mon_reply/2 + 56)# 1 2 3 4 5 6flag==1&&/^Program counter: /{print ct":", substr($4,2)}

你跟上思路没?如果跟上了,你已经了解了 Awk。恭喜!

我的博客园

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/29 5:37:16

泰克SIM软件与Python自动化实现高速信号眼图与抖动分析调试

最近在帮团队调一批高速数字单板时&#xff0c;我最大的感受是&#xff1a;真正耗时间的往往不是改电路&#xff0c;而是反反复复在示波器上抓波形、调电平、手动测量&#xff0c;再拿几十个参数回电脑上整理。尤其是眼图边缘压线、抖动数值忽高忽低的时候&#xff0c;整个调试…

作者头像 李华
网站建设 2026/8/29 5:36:31

432道MySQL面试题 81 - 100 题

为方便阅读,这里整理了整个系列的索引导航。本系列共 432 道 MySQL 面试题,按每 20 题为一篇进行连载,点击下方链接即可跳转到对应章节,方便你按需查阅、系统复习。 432道MySQL面试题 1 - 20 题 432道MySQL面试题 21 - 40 题 432道MySQL面试题 41 - 60 题 432道MySQL面试题…

作者头像 李华
网站建设 2026/8/29 5:36:03

远程手机操作手机怎么弄 如何实现手机远程控制

远程手机操作手机是当下很实用的跨设备玩法&#xff0c;很多人拥有两台及以上手机&#xff0c;急需互通协作却找不到合适工具。远程手机操作手机不用依赖复杂的技术手段&#xff0c;选对工具就能轻松实现&#xff0c;建议试试无界趣连2.0&#xff0c;适配日常协助、设备托管、日…

作者头像 李华
网站建设 2026/8/29 5:35:58

432道MySQL面试题 121 -140 题

为方便阅读,这里整理了整个系列的索引导航。本系列共 432 道 MySQL 面试题,按每 20 题为一篇进行连载,点击下方链接即可跳转到对应章节,方便你按需查阅、系统复习。 432道MySQL面试题 1 - 20 题 432道MySQL面试题 21 - 40 题 432道MySQL面试题 41 - 60 题 432道MySQL面试题…

作者头像 李华
网站建设 2026/8/29 5:31:56

TradingAgents:用多智能体协作构建金融交易决策框架

TradingAgents 最近在 GitHub 上热度不低&#xff0c;但很多人第一次看到它时容易陷入两个误区&#xff1a;一是把它当成“AI 炒股神器”&#xff0c;以为跑起来就能自动赚钱&#xff1b;二是把它当成又一个普通的大模型封装项目&#xff0c;觉得不过是套个壳调 API。这两种理解…

作者头像 李华
网站建设 2026/8/29 5:29:20

Qt 5.15.2 MinGW 64位环境编译OpenCV 4.5.5动态库完整指南

简介&#xff1a;本资源是面向Qt与OpenCV交叉开发者的预编译动态库集合&#xff0c;专为解决Windows平台下Qt5.15.2与OpenCV4.5.5协同开发时的环境配置与链接难题。采用mingw64工具链完整编译&#xff0c;同时提供带world模块&#xff08;集成全部扩展功能&#xff09;和不带wo…

作者头像 李华