AWK: A Powerful Text Processing Tool and Programming Language

Overview:
AWK is a robust text processing tool and programming language, primarily used for formatting, analyzing, and processing text on Unix and Linux systems. It excels at handling structured text like tables, CSV files, and logs.

Syntax:

awk -f 'scripts' -v var=value filename
awk 'BEGIN{ print "start" } pattern{ commands } END{ print "end" }' filename

Explanation:
AWK reads files or input streams (including stdin) line by line, processing text data based on user-specified patterns and actions. It is particularly useful for structured text. While AWK can be used directly from the command line, it is more often employed through scripts. As a programming language, AWK shares many features with C, such as arrays and functions.

Options:

  • -F: Specifies the field separator (can be a string or regular expression).
  • -f 'scripts': Reads AWK commands from the script file 'scripts'.
  • -v var=value: Assigns a value to a variable, passing external variables to AWK.

AWK Script Structure:

  • pattern: Matches specific lines.
  • { commands }: Executes actions on matching lines.
  • filename: The file to be processed by AWK.

An AWK script typically consists of three optional parts: a BEGIN block, pattern matching, and an END block. The workflow proceeds as follows:

  1. Execute the BEGIN statement.
  2. Process each line from the file or standard input, executing the pattern matching.
  3. Execute the END statement.

AWK Built-in Variables:

  • $0: The current record (line).
  • $n: The nth field (column) of the current record, where $1 is the first column and $n is the nth column.
  • FS: The field separator (default is a space or tab), can be customized with the -F option.
  • OFS: Output field separator (used for formatted output).
  • RS: Record separator (default is newline).
  • ORS: Output record separator (default is newline).
  • NR: Current line number (starting from 1).
  • NF: Number of fields (columns) in the current line.

AWK Operators:

  • Arithmetic Operators:
    +, -, *, /, %, ^
    Increment and decrement operators (++, --) can be used as prefixes or suffixes.
  • Assignment Operators:
    =, +=, -=, *=, /=, %=, ^=
  • Regular Expression Operators:
    ~: Matches regular expression.
    !~: Does not match regular expression.
  • Logical Operators:
    ||: Logical OR
    &&: Logical AND
  • Relational Operators:
    <, <=, >, >=, !=, ==
  • Other Operators:
    $: Refers to a field by its number.
    Space: Concatenates strings.
    ?:: Ternary operator.
    in: Checks if a key exists in an array.

AWK Regular Expression Syntax:

  • ^: Matches the start of a line.
  • $: Matches the end of a line.
  • .: Matches any single character.
  • *: Matches zero or more occurrences of the preceding character.
  • +: Matches one or more occurrences of the preceding character.
  • ?: Matches zero or one occurrence of the preceding character.
  • []: Matches any character in the specified range.
  • [^]: Matches any character not in the specified range.
  • () and |: Subexpressions and alternations.
  • \: Escape character.
  • {m}: Matches exactly m occurrences of a character.
  • {m,}: Matches at least m occurrences.
  • {m,n}: Matches between m and n occurrences.

AWK Built-in Functions:

  • toupper(): Converts all lowercase letters to uppercase.
  • length(): Returns the length of a string.

Custom Functions in AWK: AWK scripts can include user-defined functions. For example:

function square(x) {
  return x * x;
}

To use the function:

awk '{ print square($1) }' file.txt

AWK Control Flow Statements:

  • if-else: Conditional statements.
  • while and do-while: Loops.
  • for: Standard loops, including array traversal with for-in.
  • break and continue: Loop control.
  • exit: Terminates the script execution.
  • next: Skips the remaining commands for the current line.
  • return: Returns a value from a function.
  • ?:: Ternary operator for conditional expressions.

AWK Arrays: AWK supports associative arrays, meaning array indexes can be strings as well as numbers. Arrays in AWK don’t need to be declared or sized; they are created as soon as you assign a value to an index.

Examples:

1. Basic Example:

$ echo "hello" | awk 'BEGIN{ print "start" } END{ print "end" }'
start
end

2. Using Built-in Variables: To print the first and third columns of a file:

awk '{ print $1, $3 }' test.txt

3. Using External Variables:

$ a=100
$ b=100
$ echo | awk '{ print v1 * v2 }' v1=$a v2=$b
10000

4. Using Regular Expressions: To print the second column of lines starting with “a”:

awk '/^a/ { print $2 }' test.txt

5. Using Built-in Functions: Convert all lowercase letters to uppercase:

awk '{ print toupper($0) }' test.txt

6. Handling Different Delimiters: For CSV files with comma-separated values:

awk -F ',' '{ print $1, $2 }' test.csv

7. Writing and Running AWK Scripts: Save an AWK script to a file (e.g., script.awk):

BEGIN { FS=","; OFS=" - " }
{ print $1, $3 }

Run the script:

awk -f script.awk test.csv

Conclusion:

AWK is a versatile and powerful tool for text processing, offering rich features like pattern matching, regular expressions, and scripting capabilities. From simple one-liners to complex data analysis scripts, AWK excels at processing structured text efficiently and flexibly.

awk文本处理工具和编程语言

功能说明:awk是一个强大的文本处理工具和编程语言,主要用于在 Unix 和 Linux 系统中对文本进行格式化、分析和处理。

语  法:awk -f ‘scripts’ -v var=value filename

awk ‘BEGIN{ print “start” } pattern{ commands } END{ print “end” }’ filename

补充说明:awk 可以逐行读取文件或者输入流(包括stdin),按照用户指定的模式和操作来处理文本数据,特别适用于结构化的文本(如表格、CSV、日志等结构化数据)。awk可在命令行中使用,但更多是作为脚本来使用。awk作为一门编程语言有很多内建的功能,比如数组、函数等,这是它和C语言的相似之处。

   项:

-F                         指定分隔符(可以是字符串或正则表达式)

-f ‘scripts’             从脚本文件’scripts’中读取awk命令

-v var=value       赋值变量,将外部变量传递给awk

awk脚本基本结构:

pattern                 用于匹配特定的行

{ commands }     用于对匹配的行执行操作

filename                     要被awk处理的文件

一个awk脚本通常由BEGIN语句+模式匹配+END语句三部分组成,这三部分都是可选项。工作步骤:

第一步,执行BEGIN语句

第二步,从文件或标准输入读取一行,然后再执行pattern语句,以此类推,逐行扫描文件到文件全部被读取

第三步,执行END语句

awk内置变量:

awk默认将每行文本按照空格或特定分隔符分成多个字段(列),每个字段可以通过 $ 符号访问:

$0          当前记录(行)

$n          当前记录(行)的第n个字段(列),$1代表第1列,$n代表第n列

FS          字段(列)的分隔符(默认是空格或制表符),可以使用-F选项自定义分隔符

OFS       输出字段(列)分隔符(用于格式化输出)

RS         记录(行)的分隔符,默认是换行符

ORS      输出记录(行)的分隔符,默认是换行符

NR         当前处理的行号,默认从1开始

NF         当前行的字段(列)数

awk运算符:

算术运算符:

+     加

–      减

*     乘

/      除

%    求余

^     求幂

++         自增,作为前缀或后缀

—           自减,作为前缀或后缀

注意,非数值的变量在使用算术运算符时会被自动转换为0

赋值运算符:

=

+=

-=

*=

/=

%=

^=

正则运算符:

~     匹配正则表达式

!~    不匹配正则表达式

逻辑运算符:

||     逻辑或 

&& 逻辑与

关系运算符:

<=

>=

!=

== 

其它运算符:

$            通过序号引用字段(列)

空格      字符串链接符

?:           三目运算符

ln           数组中是否存在某键值

awk正则表达式语法:

^            行首定位符

$            行尾定位符

.             匹配任意单个字符

*            匹配0个或多个前导字符(包括回车)

+            匹配1个或多个前导字符

?            匹配0个或1个前导字符

[]           匹配指定字符组内的任意一个字符/^[ab]

[^]          匹配不在指定字符组内的任意一个字符

()           子表达式

|             或

\             转义符

~            匹配条件语句

!~           不匹配条件语句

x{m}     x字符重复m次

x{m,}    x字符至少重复m次

X{m,n} x字符至少重复m次但不起过n次(需指定选项-posix或–re-interval)

awk打印(输出)命令:

print简单输出,用于输出字段(列)或文本,自动在每个字段(列)间插入空格,并在行末自动换行

printf提供了更多格式控制,可以指定字段的输出格式、宽度、对齐方式等。它类似于 C 语言的 printf 函数。若要输出换行,需要手动添加换行符\n

awk读取输入命令:

getline用于读取文件或命令的输出

awk内置函数:

toupper函数将所有小写字母转换成大写字母

length函数返回字符个数

system函数可以用来调用系统命令,虽然它不直接打印到终端,但可以执行其他命令并返回执行结果

awk自定义函数:

awk脚本中可以定义自己的函数,例如

function square(x) {

  return x * x

}

awk ‘{ print square($1) }’ file.txt

awk流程控制语句:

if-else 条件判断

while 和 do-while 循环

for 循环,包括 for-in 数组遍历

break 和 continue 控制循环的执行

exit 终止脚本执行

next 跳过当前行

return 函数返回值

三元条件表达式 ? :

awk数组:

awk 支持关联数组,这意味着数组的索引不仅可以是整数,也可以是字符串。awk 中的数组无需声明,也不需要定义大小,直接通过索引赋值即可使用。

    例:

1 输入和输出

$ echo “hello ” | awk ‘BEGIN{ print “start” } END{ print “end” }’

start

end

打印读取到的文本:

$ echo “hello ” | awk ‘BEGIN{ print “start” } {print} END{ print “end” }’

start

hello

end

打印整行:

$ echo “Hello World” | awk ‘{print $0}’

Hello World

打印特定字段(列):

$ echo “Alice 30” | awk ‘{print $1}’ # 输出第一列,awk默认以空白符分隔列

Alice

打印多个字段:

$ echo “Alice 30” | awk ‘{print $1, $2}’

Alice 30

简单格式化输出

$ echo “Alice 30” | awk ‘{printf “%s is %d years old\n”, $1, $2}’

Alice is 30 years old

指定输出列的宽度:

$ echo “Alice 30” | awk ‘{printf “%-10s %-5d\n”, $1, $2}’ # %-10s 表示左对齐,宽度为10;%-5d 表示左对齐,宽度为5

Alice      30

控制小数点位数:

$ echo “3.14159” | awk ‘{printf “%.2f\n”, $1}’

3.14

输出到文件或追加到文件:

awk 的 print 和 printf 命令都可以配合 >, >> 操作符,将内容输出到文件中:

  • 输出到文件:使用 > 将输出重定向到文件(会覆盖文件内容)。
  • 追加到文件:使用 >> 将输出追加到文件(不会覆盖已有内容)。

将输出写入文件:

$ echo “Alice 30” | awk ‘{print $1, $2 > “output.txt”}’ # 结果输出到 output.txt 文件中

将输出追加到文件:

$ echo “Bob 25” | awk ‘{print $1, $2 >> “output.txt”}’ # 输出会追加到 output.txt 文件末尾

重定向输出到标准错误stderr:

$ echo “Error message” | awk ‘{print $0 > “/dev/stderr”}’

输出多列时自定义列的分隔符:

$ echo -e “Alice 30\nBob 25″ | awk ‘BEGIN { OFS=” | ” } {print $1, $2}’

Alice | 30

Bob | 25

使用 getline 读取文件或命令的输出:

$ awk ‘BEGIN { while ((getline line < “input.txt”) > 0) print line }’ # 从 input.txt 文件中逐行读取并输出内容

2 普通变量的定义和使用

定义多个变量,然后打印它们:

$ echo|awk ‘{ a=”aa”; b=”bb”; c=”cc”; print a,b,c; }’

aa bb cc

print语句中的””起到拼接字符串的作用:

$ echo|awk ‘{ a=”aa”; b=”bb”; c=”cc”; print a” is “b” or “c; }’

aa is bb or cc

3 内置变量的使用

打印文件中的第一列和第三列:

$ cat test.txt

aa bb cc dd ee

11 22 33 44 55

xyz yui tt

$ awk ‘{ print $1, $3 }’ test.txt

aa cc

11 33

xyz tt

$ awk ‘{ print $n }’ test.txt

aa bb cc dd ee

11 22 33 44 55

xyz yui tt

打印第二列第一列并以,符号分隔:

$ awk ‘{print $2″,”$1}’  test.txt

bb,aa

22,11

yui,xyz

打印每行的行号和字段(列)数:

$ awk ‘{ print NR, NF }’ test.txt

1 5

2 5

3 3

4 外部变量的使用

$ a=100

$ b=100

$ echo |awk ‘{print v1*v2 }’ v1=$a v2=$b

10000

$ e=eee

$ echo |awk ‘{print e }’ e=$e

eee

在shell中,awk可以直接使用shell的环境变量。

5 awk运算符的使用

$ awk ‘BEGIN{a=”b”;print a,a++,a–,++a;}’

b 0 1 1

$ awk ‘BEGIN{a=”0″;print a,a++,a–,++a;}’

0 0 1 1

$ awk ‘BEGIN{a=7;b=2;print a/b;}’

3.5

$ awk ‘BEGIN{a=7;b=2;print a%b;}’

1

$ awk ‘BEGIN{a=7;b=2;print a^b;}’

49

$ awk ‘BEGIN{a=7;b=2;print a==b;}’

0

$ awk ‘BEGIN{a=7;b=2;print a=b;}’

2

打印第二列是22的行第一列:

$ cat test.txt

aa bb cc dd ee

11 22 33 44 55

xyz yui tt

$ awk ‘($2 == 22) {print $1}’ test.txt

11

打印第3列的值大于66的行:

$ awk ‘$3 > 66’ test.txt

aa bb cc dd ee

xyz yui tt

? :三目运算符的使用示例:

$ awk ‘BEGIN{a=”b”;print a==”b”?”yes”:”no”}’

yes

6 正则表达式的使用

$ cat test.txt

aa bb cc dd ee

11 22 33 44 55

xyz yui tt

打印以a开头的行的第2列:

$ awk ‘/^a/{print $2}’ test.txt

bb

打印以a开头的行的第2列,并在第2列前加上aaa子串:

$ awk ‘/^a/{print “aaa”$2}’ test.txt

aaabb

打印第1列匹配xyz的行的第3列的值:

$ awk ‘$1~/xyz/ {print $3}’ test.txt

tt

如果变量a中包含test子串,那么打印yes:

$ echo|awk ‘BEGIN{a=”100testaaa”}a~/test/{print “yes”}’

yes

输出所有包含子串root的行:

awk ‘/root/{print $0}’ test.txt

7 awk内置函数的使用

toupper函数将所有小写字母转换成大写字母:

$ cat test.txt

aa bb cc dd ee

11 22 33 44 55

xyz yui tt

$ awk ‘{print toupper($0)}’ test.txt

AA BB CC DD EE

11 22 33 44 55

XYZ YUI TT

length函数返回字符个数。打印长度为3个字符的第一列的内容:

$ awk ‘{if(length($1) == 3) print $1}’ test.txt

xyz

8 处理不同分隔符的文件

通过设置 -F 选项来指定输入的字段的分隔符。例如,对于以逗号分隔的 CSV 文件:

$ cat test.csv

ttc,yui,layui,tailwind

c,c++,go,java,python,php,js

apple,google,facebook,reddit,twitter,amazon

john@Ubuntu22-VirtualBox:~/test$ awk -F ‘,’ ‘{ print $1, $2 }’ test.csv

ttc yui

c c++

apple google

如果不使用-F ‘,’选项,就无法正确处理CSV文件:

$ awk ‘{ print $1, $2 }’ test.csv

ttc,yui,layui,tailwind

c,c++,go,java,python,php,js

apple,google,facebook,reddit,twitter,amazon

9 awk脚本的编写和使用

除了命令行上使用,我们也可以编写awk脚本文件,适合复杂的数据处理任务。例如,保存以下代码到 script.awk 文件中:

BEGIN { FS=”,”; OFS=” – ” }

{ print $1, $3 }

然后用 awk -f script.awk test.csv 来执行这个脚本:

$ awk -f script.awk test.csv

ttc – layui

c – go

apple – facebook

10 控制流程的使用

10.1 if-else 语句(条件判断)

$ cat test.txt

aa bb cc dd ee

11 22 33 44 55

xyz yui tt

$ awk ‘{ if ($3 > 66) print $1, $3; else print $3, “not greater” }’ test.txt

aa cc

33 not greater

xyz tt

可以嵌套多个 if-else 语句:

awk ‘{ if ($1 > 10) print “Greater”; else if ($1 == 10) print “Equal”; else print “Smaller” }’ file.txt

10.2 while 语句(循环)

awk ‘{ i = 1; while (i <= NF) { print $i; i++ } }’ file.txt

10.3 do-while 语句(后测试循环)

do-while 循环会先执行一次循环体,然后检查条件是否为真:

awk ‘{ i = 1; do { print $i; i++ } while (i <= NF) }’ file.txt

10.4 for 语句(循环)

awk ‘{ for (i = 1; i <= NF; i++) print $i }’ file.txt

10.5 for-in遍历数组的所有索引

awk ‘{ for (i in arr) print arr[i] }’

10.6 break 语句(跳出循环)

awk ‘{ for (i = 1; i <= NF; i++) { if ($i == “stop”) break; print $i } }’ file.txt

10.7 continue 语句(继续下一次循环)

continue 语句用于跳过本次循环的剩余部分,并继续执行下一次循环:

awk ‘{ for (i = 1; i <= NF; i++) { if ($i == “skip”) continue; print $i } }’ file.txt

10.8 exit 语句(退出程序)

exit 语句用于终止 awk 脚本的执行,退出脚本时可以指定退出状态码:

awk ‘{ if ($1 == “exit”) exit; print $1 }’ file.txt

立即终止脚本的执行,剩余的行不会被处理。

可以在 END 块中使用 exit 返回状态码:

awk ‘END { if (NR == 0) exit 1 }’ file.txt

10.9 next 语句(跳到下一行)

next 语句用于跳过当前行的剩余操作,直接处理下一行:

awk ‘{ if ($1 == “skip”) next; print $1 }’ file.txt

10.10 return 语句(函数中使用)

return 语句用于在函数中返回值并退出函数:

function square(x) {

  return x * x

}

awk ‘{ print square($1) }’ file.txt

10.11 条件表达式(三元操作符)

awk ‘{ print ($1 > 10 ? “Greater” : “Smaller”) }’ file.txt

11 数组

11.1 定义和使用数组

awk 中通过赋值操作可以直接定义数组。例如:

awk ‘BEGIN { arr[1] = “apple”; arr[2] = “banana”; print arr[1], arr[2] }’

在这个例子中,arr[1] 和 arr[2] 定义了两个元素,分别存储 “apple” 和 “banana”。

使用字符串作为数组的索引:

awk ‘BEGIN { arr[“fruit”] = “apple”; print arr[“fruit”] }’

11.2 遍历数组

你可以使用 for-in 循环遍历数组中的所有元素,数组中的索引会被 for 循环访问:

awk ‘BEGIN {

    arr[1] = “apple”;

    arr[2] = “banana”;

    arr[3] = “cherry”;

    for (i in arr) {

        print i, arr[i];

    }

}’

这个例子会遍历数组 arr,输出数组的索引和对应的值。值得注意的是,awk 中 for-in 循环的遍历顺序并不保证是按索引的顺序,具体顺序取决于 awk 的实现。

11.3 删除数组元素

可以使用 delete 语句删除数组中的某个元素:

awk ‘BEGIN {

    arr[1] = “apple”;

    arr[2] = “banana”;

    delete arr[1];

    print arr[1];  # 输出为空,因为arr[1]已被删除

}’

delete 会将指定的数组元素完全移除,后续对该索引的访问将返回空值。

11.4 计算数组长度

awk 本身没有直接的函数来计算数组的长度,但你可以通过遍历数组来计算元素个数。例如:

awk ‘BEGIN {

    arr[1] = “apple”;

    arr[2] = “banana”;

    arr[3] = “cherry”;

    count = 0;

    for (i in arr) {

        count++;

    }

    print “Array length:”, count;

}’

11.5 多维数组

虽然 awk 本质上是支持一维数组,但可以通过组合索引来实现多维数组的效果。你可以使用多个索引作为键,例如:

awk ‘BEGIN {

    arr[1,1] = “apple”;

    arr[1,2] = “banana”;

    arr[2,1] = “cherry”;

    print arr[1,1];  # 输出apple

    print arr[1,2];  # 输出banana

    print arr[2,1];  # 输出cherry

}’

这里 arr[1,1] 和 arr[1,2] 类似于二维数组的定义,逗号 , 将多个索引组合在一起。

11.6 数组的默认值

在 awk 中,未被初始化的数组元素会默认返回空字符串或 0,具体取决于如何使用。例如:

awk ‘BEGIN {

    print arr[1];  # 输出为空,因为arr[1]未被初始化

}’

如果试图对一个未初始化的数组元素进行运算操作,它将被视为 0。

12 综合实例

获取enp0s3网卡的IP地址:

$ ifconfig enp0s3|awk ‘BEGIN{FS=”[[:space:]:]+”} NR==2{print $3}’

10.0.2.15

打印当前目录下的子目录和文件的总字节数,以MB为单位:

$ ls -alh|awk ‘BEGIN{size=0;} {size=size+$5;} END{print “total size is “,size/1024/1024,”MB”}’

total size is  0.000601768 MB