【linux】awk命令

1. AWK 工作流程

这一章节中,我们将解释 AWK 是如何工作的。 要想成为 AWK 专家,你必须得了解其内部工作的原理。 AWK 执行的流程非常简单:读( Read )、执 行( Execute )与重复( Repeat )。下面的流程图描述出了 AWK 的工作流程:
在这里插入图片描述
完整的示例

' BEGIN {awk-commands-begin}     {awk-commands-body}     END {awk-commands-end}      '
  • 单引号包围的是整个 awk 程序。 单引号是必须存在的!!!!
    双引号表示字符串,下面示例中有

  • 其中 BEGIN 和END 可以省略

  • body部分会按行重复执行
    读(Read):
    AWK 从输入流(文件、管道或者标准输入)中读入一行然后将其存入内存中。

    执行(Execute):
    对于每一行输入,所有的 AWK 命令按顺执行。 默认情况下,AWK 命令是针对于每一行输入,但是我们可以将其限制在指定的模式中。

    重复(Repeate):
    一直重复上述两个过程直到文件结束。

开始块(BEGIN block)
开始块的语法格式如下所示:

BEGIN {awk-commands}

顾名思义,开始块就是在程序启动的时候执行的代码部分,并且它在整个过程中只执行一次。 一般情况下,我们在开始块中初始化一些变量。BEGIN 是 AWK 的关键字,因此它必须是大写的。 不过,请注意,开始块部分是可选的,你的程序可以没有开始块部分。

主体块(Body Block)
主体部分的语法要求如下:

/pattern/ {awk-commands}

对于每一个输入的行都会执行一次主体部分的命令。默认情况下,对于输入的每一行,AWK 都会很执行命令。但是,我们可以将其限定在指定的模式中。 注意,在主体块部分没有关键字存在。

  • pattern 一般是过滤条件 ,例如下面的 NR==1等
  • {} 及里面的内容是可选的

结束块(END Block)
下面是结束块的语法格式:

END {awk-commands}

结束块是在程序结束时执行的代码。 END 也是 AWK 的关键字,它也必须大写。 与开始块相似,结束块也是可选的。并且它在整个过程中只执行一次

1.1 示例

先创建一个名为 marks.txt 的文件。其中包括序列号、学生名字、课程名称与所得分数。

1)    Amit     Physics    80
2)    Rahul    Maths      90
3)    Shyam    Biology    87
4)    Kedar    English    85
5)    Hari     History    89

接下来,我们将使用 AWK 脚本来显示输出文件中的内容,同时输出表头信息。

[jerry]$ awk 'BEGIN{printf "Sr No\tName\tSub\tMarks\n"} {print}' marks.txt

执行上面的代码后,将会输出如下的结果:

Sr No Name     Sub        Marks
1)    Amit     Physics    80
2)    Rahul    Maths      90
3)    Shyam    Biology    87
4)    Kedar    English    85
5)    Hari     History    89

程序启动时,AWK 在开始块中输出表头信息。在主体块中,AWK 每读入一行就将读入的内容输出至标准输出流中,一直到整个文件被全部读入为止。

2. AWK 内置变量

AWK 提供了一些内置变量。 它们在你写 AWK 脚本的时候起着很重要的作用。 这一章节中将会展示如何使用这些内置变量。

2.1 ARGC

ARGC 表示在命令行提供的参数的个数。

[jerry]$ awk 'BEGIN {print "Arguments =", ARGC}' One Two Three Four

执行上面的命令可以得到如下的结果:

Arguments = 5

程序哪儿出毛病了吗?为什么只输入四个参数而 AWK 却显示输入的参数个数的五呢? 看完下面这个例子,你就会明白的。

2.2 ARGV

这个变量表示存储命令行输入参数的数组。数组的有效索引是从 0 到 ARGC-1。

[jerry]$ awk 'BEGIN { for (i = 0; i < ARGC - 1; ++i)
      { printf "ARGV[%d] = %s\n", i, ARGV[i] } 
                    }' one two three four

执行上面的命令可以得到如下的结果:

ARGV[0] = awk
ARGV[1] = one
ARGV[2] = two
ARGV[3] = three

2.3 CONVFMT

此变量表示数据转换为字符串的格式,其默认值为 %.6g。

[jerry]$ awk 'BEGIN { print "Conversion Format =", CONVFMT }'

执行上面的命令可以得到如下的结果:

Conversion Format = %.6g 

2.4 ENVIRON

此变量是与环境变量相关的关联数组变量。

[jerry]$ awk 'BEGIN { print ENVIRON["USER"] }'

执行上面的命令可以得到如下的结果:

jerry

可以使用 GNU/Linux 系统中的 env 命令查询其它环境变量的名字。

2.5 FILENAME

此变量表示当前文件名称。

[jerry]$ awk 'END {print FILENAME}' marks.txt

执行上面的命令可以得到如下的结果:

marks.txt

值得注意的是在开始块中FILENAME是未定义的。

2.6 NF

此变量表示当前输入记录的列数。例如,下面这个例子只输出超过两个列的行:

[jerry]$ echo -e "One Two\nOne Two Three\nOne Two Three Four" | awk 'NF > 2'

等价于 ,默认是打印全部:

[jerry]$ echo -e "One Two\nOne Two Three\nOne Two Three Four" | awk 'NF > 2 { print}'

执行上面的命令可以得到如下的结果:

One Two Three
One Two Three Four

2.7 NR(number of row)

此变量表示当前记录的行号。(译注:该变量类似一个计数器,统计记录的数量)。下面例子会输出读入的前三行(NR<3)。

[jerry]$ echo -e "One Two\nOne Two Three\nOne Two Three Four" | awk 'NR < 3  { print}'

执行上面的命令可以得到如下的结果:

One Two
One Two Three

2.8 FNR

该变量与 NR 类似,不过它是相对于当前文件而言的。此变量在处理多个文件输入时有重要的作用。每当从新的文件中读入时 FNR 都会被重新设置为 0。

2.9 FS

此变量表示输入的数据域之间的分隔符,其默认值是空格。 你可以使用 -F 命令行选项改变它的默认值。

[jerry]$ awk 'BEGIN {print "FS = " FS}' | cat -vte

执行上面的命令可以得到如下的结果:

FS =  $

cat -vte 此命令会以可视方式显示所有特殊字符(包括制表符、换页符等),并在行尾显示"$"符号。

2.10 RS (row separate)

此变量表示输入记录的分割符,其默认值为换行符。

[jerry]$ awk ‘BEGIN {print "RS = " RS}’ | cat -vte
执行上面的命令可以得到如下的结果:

RS = $
$

2.11 OFS

此变量表示输出域之间的分割符,其默认为空格。

[jerry]$ awk 'BEGIN {print "OFS = " OFS}' | cat -vte

执行上面的命令可以得到如下的结果:

OFS = $

2.12 ORS (output row separate)

此变量表示输出记录(行)之间的分割符,其默认值是换行符。

[jerry]$ awk 'BEGIN {print "ORS = " ORS}' | cat -vte

执行上面的命令可以得到如下的结果:

ORS = $
$

2.13 $0:当前处理行的整行内容

2.14 $n:当前处理行的第 n 个字段(第 n 列)

3. 运算符

与其它编程语言一样,AWK 也提供了大量的操作符。这一章节中,我们将结合例子介绍 AWK 操作符的使用方法: 
完整参见 AWK 操作符

3.1 算术运算符

AWK 支持如下的算术运算符:

3.1.1加法运算符

加法运算由符号 + 表示,它求得两个或者多个数字的和。下面是一个使用示例:

[jerry]$ awk 'BEGIN { a = 50; b = 20; print "(a + b) = ", (a + b) }'

执行上面的命令可以得到如下的结果:

(a + b) =  70

4. AWK 正则表达式

4.1 点(Dot)

点字符(.)可以匹配除了行结束字符的所有字符,只能出现一次,且必须出现一次。比如下面的便子就可以匹配 fin, fun, fan 等等。

echo -e "cat\nbat\nfun\nfin\nfn\nfaan" | awk '/f.n/'

示例中的-e是为了构建换行的。

执行上面命令可以得到如下结果:

fun
fin

4.2 行开始

行开始符(^)匹配一行的开始。下面的示例将输出所有以字符串 The 开始的行。

[jerry]$ echo -e "This\nThat\nThere\nTheir\nthese" | awk '/^The/'

执行上面的命令可以得到如下结果:

There
Their

4.3 行结束

行结束符($)匹配一行的结束。下面的例子中将输出所有以字符 n 结束的行:

> [jerry]$ echo -e "knife\nknow\nfun\nfin\nfan\nnine" | awk '/n$/'

执行上面的命令可以得到如下结果:

fun
fin
fan

4.4 匹配字符集

匹配字符集用于匹配集合(由方括号表示)中的一个字符。如下例子中,匹配 Call 与 Tall 而不会匹配 Ball。

[jerry]$ echo -e "Call\nTall\nBall" | awk '/[CT]all/'

执行上面的命令可以得到如下结果:

Call
Tall

4.5 排除集

正则匹配时会排除集合中的字符。如下例子中只会输出 Ball。

[jerry]$ echo -e "Call\nTall\nBall" | awk '/[^CT]all/'

执行上面的命令可以得到如下结果:

Ball


竖线(|)允许正则表达式实现逻辑或运算. 下面例子将会输出 Ball 与 Call 。

[jerry]$ echo -e "Call\nTall\nBall\nSmall\nShall" | awk '/Call|Ball/'

执行上面的命令可以得到如下结果:

Call
Ball

4.6?最多出现一次

该符号( ?)前面单个字符出现0次或者出现一次。如下示例匹配 Colour 与 Color。 使用 ? 使得 u 变成了可选字符 。

[jerry]$ echo -e "Colour\nColor" | awk '/Colou?r/'

执行上面的命令可以得到如下结果:

Colour
Color

4.7 出现零次或多次

该符号(*) 允许其前面单个字符出现多次或者0次。如下示例将匹配 ca,cat, catt 等等。

[jerry]$ echo -e "ca\ncat\ncatt" | awk '/cat*/'

执行上面的命令可以得到如下结果:

ca
cat
catt

4.8 出现一次或多次

该符号(+)使得其前的字符出现一次或者多次。下面的例子会匹配一个 2 或者多个连续的 2。

[jerry]$ echo -e "111\n22\n123\n234\n456\n222"  | awk '/2+/'

执行上面的命令可以得到如下结果:

22
123
234
222

4.9 分组

括号用于分组而字符 | 用于提供多种选择。如下的正则表达式会匹配所有包含 Apple Juice 或 Aplle Cake 的行。

与前面 [] 区别在于,[]是取单个字符,而这里是取一个字符串

[jerry]$ echo -e "Apple Juice\nApple Pie\nApple Tart\nApple Cake" | awk '/Apple (Juice|Cake)/'

执行上面的命令可以得到如下结果:

Apple Juice
Apple Cake

5. 控制语句

5.1 IF 语句

条件语句测试条件然后根据条件选择执行相应的动作。下面是条件语句的语法:

if (condition)
    action

也可以使用花括号来执行一组操作:

if (condition)
{
    action-1
    action-1
    .
    .
    action-n
}

下面的例子判断数字是奇数还是偶数:

[jerry]$ awk 'BEGIN {num = 10; if (num % 2 == 0) printf "%d is even number.\n", num }'

执行上面的命令可以得到如下的结果:

10 is even number.

5.2 IF - ELSE 语句

if-else语句中允许在条件为假时执行另外一组的动作。下面为 if-else 的语法格式:

if (condition)
    action-1
else
    action-2

其中,条件为真时执行 action-1,条件为假时执行 action-2。下面是使用该语句判断数字是否为偶数的例子:

[jerry]$ awk 'BEGIN {num = 11; 
   if (num % 2 == 0) printf "%d is even number.\n", num; 
   else printf "%d is odd number.\n", num 
                    }'

执行上面的操作可以得到如下的结果:

11 is odd number.

5.3 if-else-if 梯

我们可以很轻松地使用多个 if-else 语句构造 if-else-if 梯从而实现多个条件的判断。示例如下:

[jerry]$ awk 'BEGIN {
a=30;
if (a==10)
  print "a = 10";
else if (a == 20)
  print "a = 20";
else if (a == 30)
  print "a = 30";
}'

执行上面的命令可以得到如下的结果:

a = 30

6. AWK 循环

6.1 For

For 循环的语法如下:

for (initialisation; condition; increment/decrement)
    action

for 语句首先执行初始化动作( initialisation ),然后再检查条件( condition )。如果条件为真,则执行动作( action ),然后执行递增( increment )或者递减( decrement )操作。只要条件为真循环就会一直执行。每次循环结束都会进条件检查,若条件为假则结束 循环。下面的例子使用 For 循环输出数字 1 至 5:

[jerry]$ awk 'BEGIN { for (i = 1; i <= 5; ++i) print i }'

执行上面的命令可以得到如下结果:

1
2
3
4
5

6.2 While

While 循环会一直执行动作直到逻辑条件为假为止。其使用方法如下:

while (condition)
    action

AWK 首先检查条件是否为真,若条件为真则执行动作。此过程一直重复直到条件为假时,则停止。下面是使用 While 循环输出数字 1 到 5 的例子:

[jerry]$ awk 'BEGIN {i = 1; while (i < 6) { print i; ++i } }'

执行上面的命令可以得到如下的结果:

1
2
3
4
5

6.3 Do-While

Do-While 循环与 While 循环相似,但是 Do-While 的条件测试放到了循环的尾部。下面是 do-while 的语法:

do
    action
while (condition)

在 do-while 循环中,无论条件是真是假,循环语句至少执行一次,执行后检查条件真假。下面是使用 do-While 循环输出数字 1 到 5 的例子:

[jerry]$ awk 'BEGIN {i = 1; do { print i; ++i } while (i < 6) }'

执行上面的命令可以得到如下的结果:

1
2
3
4
5

6.4 Break

顾名思义,break 用以结束循环过程。在下面的示例子中,当计算的和大于 50 的时候使用 break 结束循环过程:

[jerry]$ awk 'BEGIN {
    sum = 0; for (i = 0; i < 20; ++i) { 
         sum += i; if (sum > 50) break; else print "Sum =", sum 
                                      } 
                    }'

执行上面的命令可以得到如下的结果:

Sum = 0
Sum = 1
Sum = 3
Sum = 6
Sum = 10
Sum = 15
Sum = 21
Sum = 28
Sum = 36
Sum = 45

6.5 Continue

Continue 语句用于在循环体内部结束本次循环,从而直接进入下一次循环迭代。当我们希望跳过循环中某处数据处理时就会用到 Continue。下面的例子输出 1 到 20 之间的偶数:

[jerry]$ awk 'BEGIN {for (i = 1; i <= 20; ++i) {if (i % 2 == 0) print i ; else continue} }'

执行上面的命令可以得到如下的结果:

2
4
6
8
10
12
14
16
18
20

6.6 Exit

Exit 用于结束脚本程序的执行。该函数接受一个整数作为参数表示 AWK 进程结束状态。 如果没有提供该参数,其默认状态为 0 。下面例子中当和大于 50 时结束 AWK 程序。

[jerry]$ awk 'BEGIN {
    sum = 0; for (i = 0; i < 20; ++i) {
        sum += i; if (sum > 50) exit(10); else print "Sum =", sum 
                                     } 
                    }'

执行上面的命令可以得到如下的结果:

Sum = 0
Sum = 1
Sum = 3
Sum = 6
Sum = 10
Sum = 15
Sum = 21
Sum = 28
Sum = 36
Sum = 45

让我们检查一下脚本执行后的返回状态:

[jerry]$ echo $?

执行上面的命令可以得到如下的结果:

10

参考

https://www.w3cschool.cn/awk/27bx1k8p.html

  • 25
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux awk命令是一种强大的文本分析工具,它可以帮助用户从文本文件或标准输入中抽取信息并进行处理。下面是关于awk命令的一些基本用法、工作流程、常用选项参数说明、实操案例和常用awk的内置变量: 1. 基本用法 awk命令的基本语法为: ``` awk 'pattern {action}' file ``` 其中,pattern是一个模式,用于匹配文件中的文本;action是一个动作,用于在匹配到的文本上执行的操作;file是要处理的文件名。 2. 工作流程 awk命令的工作流程如下: - 读入文件的第一行,并根据指定的分隔符将其分割成多个字段。 - 对于每一行,awk命令都会执行pattern-action语句,如果pattern匹配成功,则执行action操作。 - 重复执行步骤2,直到文件的所有行都被处理完毕。 3. 常用选项参数说明 - -F:指定输入文件的分隔符。 - -v:定义一个变量并赋值。 - -f:指定awk程序文件的路径。 4. 实操案例 假设有一个名为test.txt的文件,内容如下: ``` Tom 20 male Jerry 18 female Mike 22 male ``` 现在我们想要从中抽取出所有男性的姓名和年龄,可以使用如下命令: ``` awk '$3=="male"{print $1,$2}' test.txt ``` 输出结果为: ``` Tom 20 Mike 22 ``` 5. 常用awk的内置变量 - $0:表示整个文本行。 - $1、$2、$3...:表示文本行中的第1、2、3...个字段。 - NR:表示awk已经读入的记录数。 - NF:表示当前记录中的字段数。 - FS:表示输入字段分隔符。 - RS:表示输入记录分隔符。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值