shell三剑客之awk 数据截取工具 详解

目录

awk 数据截取工具

①awk简介

②awk语法结构

OPTIONS

PROGRAM

pattern

action

③变量

④流程控制

⑤数组

⑥内建函数

扫描二维码关注公众号,回复: 3798823 查看本文章

 


 

awk简介

>>>awk是一种编程语言(解释性语言,不需要编译),用于数据截取和报告的工具

>>>awk自动搜索输入的文件,并把每个输入行切分成多个字段(字段:根据分隔符分割成的单元)

>>>擅长处理数据库和表型数据。适合编写短小一次性程序

>>>centos默认的awk使用的是gawk系统将awk通过软链接来指向gawk

>>>可以使用新的内置函数和变量

>>>在缺省的情况下,它使用扩展的正则表达式

>>>awk不需要声明变量的数据类型,它内置字符串类型和数值类型

 


 

awk语法结构

awk [OPTIONS] [--] program filename_list

 

一个案例理解awk

>>>date文件第一列为员工名字,第二列为时薪,第三列为工作时长

>>>需求:打印输出时薪大于等于50,的员工名字和总薪资

[bei@localhost test]$ cat date

Sam 50 8

Bei 55 7

Tom 48 9

Tim 80 8

[bei@localhost test]$ awk '$2 >= 50 { print $1,$2*$3 }' date

Sam 400

Bei 385

Tim 640

说明:awk命令后面的程序用单引号引起来,单引号后面的部分为输入文件

单引号中包围的内容是一个awk程序,是一个program即模式-动作语句(pattern-action

其中模式pattern'$2>=50',表示扫描每一个输入的行,如果第二列大于0,则执行动作action,否则不执行action

动作action'{ print $1,$2*$3 }',模式匹配成功后执行的对应动作,该动作用于打印输出第一个字段和第二、三字段的乘积

 

OPTIONS

选项

描述

-V

显示awk的版本

-f program-file

指定包含了awk命令的文件,不是从命令行参数中去读取
可以通过-f选项指定多个包含awk命令文件

-F'fs'

--field-separator

指定分隔符即为定义FS变量对应的值

-v var=val

在程序开始之前,将val这个值赋给var这个变量

-d[file]

将全局变量的类型和最终值排序,并将排序好后的结果打印输出到文件中

 

 

PROGRAM——'pattern{ action }'awk的核心)

关于pattern { action }的说明:

>>>pattern与action并非同时存在,可以省略其中一个

>>>如果action被省略,默认动作是将每个匹配的行输出

>>>如果pattern被省略,对于每行都会执行动作

 

awk基本操作流程:

>>>从输入流中读取一行内容,然后使用pattern{action}去处理

>>>对读取的行进行扫描搜索,搜索行中是否有内容被pattern匹配

>>>如果行被pattern匹配成功,则执行动作{action}

       如果行中内容不被pattern匹配,则不输出

>>>继续从输入流中读取新的一行,重复上述几个步骤

 

 

pattern

>>>pattern,即模式,是决定awk程序中定义的动作action是否能够被执行的关键

>>>pattern支持的规则:正则表达式,字符串与数字比较,流程控制语句

模式表示方式汇总:

BEGIN 

END  

/regexp/

relational expression

pattern && pattern

pattern || pattern

 

BEGIN  :放在程序开头,当awk从输入流中读取数据之前,BEGIN语句开始执行(初始化

                   常见用法:改变分隔符 (FS、OFS、ORS)

           可以执行多个BEGIN,按顺序执行,多个END同样适用

END     :放在程序末尾,当所有输入流被读取完毕,END语句开始执行(扫尾

>>>案例

[bei@localhost test]$ cat date
Sam 50 8
Bei 55 7
Tom 48 9
Tim 80 8
[bei@localhost test]$ awk 'BEGIN{OFS=":";ORS="\n\n"} BEGIN{print "name:total_salary"} {print $1,$2*$3}' date
name:total_salary

Sam:400

Bei:385

Tom:432

Tim:640

说明:第一个BEGIN是对输出字段分隔符OFS和输出记录分隔符ORS的赋值

          第二个BEGIN语句是输出字符串 "name:total_salary"

          执行完BEGIN后,awk再从输入流中读取处理数据

 

正则之字符串匹配模式/regexp/(使用的是拓展的正则表达式)

>>>/regexp/

当前输入行包含能被regexp匹配的子字符串时,该模式被匹配

>>>expression ~ /regexpr/ 

允许正则表达式限定在记录中的特定字段

例如$1 ~ /regexp/ 只匹配第一个字段符合表达式的记录,若$1匹配/regexp/,则模式被匹配

>>>expression !~ /regexpr/ 

expression不包含regexp字符,则模式被匹配

 

模式表达式 relational expression

>>>当表达式拥有一个数值形式的值,运算符要求一个字符串值,则awk会将该数值自动转换成字符串

>>>当表达式拥有一个字符串形式的值,运算符要求一个数值,则awk会将该字符串值自动转换成数值

>>>关于表达式真与假的说明:如果一个表达式,对当前述入行的求值结果非零或不为空,那么该行就被匹配

>>>如果比较字符串,比较时是逐字符依赖ASCII字符表比较

比较运算符汇总

运算符

描述

<

小于

<=

小于等于

==

等于

!=

不等于

>

大于

>=

大于等于

~

匹配

!~

不匹配

表达式运算符汇总(也可以用在action

操作

运算符

例子

赋值

=+=-=*=/=^=

sum+=i 即sum=sum+i

条件表达式

:

x?y:z x为真则为y,否则为z

逻辑或

||

x||y   若x或y为真,则表达式为真

逻辑与

&&

x&&y 若x与y都为真,则表达式为真

数组成员

in

i in a

匹配

不匹配

~

~

 

自增自减

++--

 

字段

$

$1 表示输入行的第一个字段

组合

(  )

($2+1) 表示第三个字段

 

复合模式

>>>通过()括号、||或、&&与、!非 组合

pattern && pattern

pattern || pattern

需求:输出txt第一和二个字段都为数字或第三和四个字段都为字母的行

[bei@localhost test]$ cat txt
1 2 1 2
2 3 2 a
3 2 a b
4 a b d
a b 1 2
[bei@localhost test]$ awk '($1~/[0-9]/&&$2~/[0-9]/)||($3~/[a-zA-Z]/&&$4~/[a-zA-Z]/){print $0}' txt
1 2 1 2
2 3 2 a
3 2 a b
4 a b d

说明:$1~/[0-9]/与$2~/[0-9]/之间和$3~/[a-zA-Z]/与$4~/[a-zA-Z]之间是与的关系

          ($1~/[0-9]/&&$2~/[0-9]/)和($3~/[a-zA-Z]/&&$4~/[a-zA-Z]/)之间是或的关系

 

 

action

格式化输出

>>>在print语句中,多个变量之间使用逗号作为分隔符,对变量进行分隔

案例

[bei@localhost test]$ cat awk.txt
Beth 3.00 0
Susie 4.50 40
Bei 4.00 50
Dan 4.00 50
[bei@localhost test]$ cat awk.txt | awk '{print $1,$2}'
Beth 3.00
Susie 4.50
Bei 4.00
Dan 4.00
>>>NF(number of field)表示字段数,$NF表示最后一个字段
[bei@localhost test]$ awk '{print NF,$1,$NF}' awk.txt    
3 Beth 0
3 Susie 40
3 Bei 50
3 Dan 50

>>>awk提供了一个内建变量NRnumber of row),该变量用于记录当前从输入流中读取的行的行号

需求:输出时在每一行行首加上行号     

[bei@localhost test]$ awk '{print NR,$0}' awk.txt     
1 Beth 3.00 0
2 Susie 4.50 40
3 Bei 4.00 50
4 Dan 4.00 50

        #可以将字符串放在字段中的任意位置

[bei@localhost test]$ awk '{print ("The line_number is",NR,$0)}' awk.txt
The line_number is 1 Beth 3.00 0
The line_number is 2 Susie 4.50 40
The line_number is 3 Bei 4.00 50
The line_number is 4 Dan 4.00 50

>>>awk分隔符:FS变量、OFS变量和ORS变量

FSField Separator)字段分隔符,即读取输入流时,以FS作为字段分隔的依据,默认情况下为一个空格符

OFSOutput Field Separator)输出字段分隔符,默认情况下为一个空格符

ORSOutput Record Separator)输出记录分隔符,默认情况下为一个换行符

#需求:print输出/etc/passwd的第一列和最后一列,字段之间用冒号隔开,每一行之间还有一个空行

[bei@localhost test]$ awk 'BEGIN{FS=":";OFS=":";ORS="\n\n"}{print $1,$NF}' /etc/passwd
root:/bin/bash

bin:/sbin/nologin

daemon:/sbin/nologin

adm:/sbin/nologin

……

注意:对变量FSOFSORS赋值时,需要使用双引号,不能没有引号或使用单引号

>>>printf语句

语法格式:printf(format,expression1,expression2…)

>>>参数format是必须的,包含百分号%、对齐方式、格式控制字符、字符串最大宽度format最后需要添加\n才会换行)

>>>format 之间不用 ","隔开 而是用空格隔开

printf格式控制字符

字符

表达式将被打印成

$1

printf(format$1)

%c

ASCII字符

97

a

%d

十进制整数

97.5

97

%5d

 

97.5

   97

%e

[-]d.dddddd[+-]dd

97.5

9.750000e+01 01表示10的次方为1

%f

[-]ddd.dddddd

97.5

97.500000

%7.2f

 

97.5

     97.50

%g

按照ef进行转换

97.5

97.5

%o

无符号八进制数

97

141

%06o

 

97

000141

%x

无符号十六进制数

97

61

%s

字符串

January

January

%10s

 

January

   January

%-10s

 

January

January   (后面还有三个空格)

%.3s

 

January

Jan

%10.3s

 

January

       Jan

%-10.3s

 

January

Jan       (后面还有七个空格)

%

打印一个百分号%,不会有参数被吸收

 

 

对齐方式:

连字符 '-' 表示左对齐,不使用连字符默认是右对齐

字符串最大宽度:

为了达到规定宽度,必要时填充空格,前导的0用零填充

 

>>>awk程序可以使用重定向运算符>>>
        使用>>重定向,打开文件时,不会清空文件内容,并追加文件到尾部
        使用重定向,打开文件时,会清空文件内容,再把内容追加到文件

awk '$3 > 100 {print $0 >> "file_01"}'

注意:重定向时,文件名必须使用双引号引起来,否则会将其当做一个未初始化的变量来使用

awk '$3 > 100 {print $0 > "file_01"}'

重定向时,会先将文件file_01原来的内容删除,相当于覆盖原来的内容

 

输出到管道|,并排序sort

>>>语句: {print(…)|"sort …"} 注意:sort命令需要用双引号引起来

需求:date文件是三门科目的考试成绩,需要格式化输出(名字,三科成绩,总成绩),再以总成绩降序排序

[bei@localhost test]$ cat date
Simon 96 97 99
Bei 92 100 95
Tom 100 92 97
Tim 80 99 99
[bei@localhost test]$ awk '{printf("%-7s %-3d %-3d %-3d %-3d\n",$1,$2,$3,$4,$2+$3+$4)|"sort -nr -k 5"}' date 
Simon   96  97  99  292
Tom     100 92  97  289
Bei     92  100 95  287
Tim     80  99  99  278

#或者将awk的输出通过管道符传递给sort命令实现将格式化输出后的内容进行排序

[bei@localhost test]$ awk '{printf("%-7s %-3d %-3d %-3d %-3d\n",$1,$2,$3,$4,$2+$3+$4)}' date | sort -nr -k 5

 


 

③变量

>>>表达式可以包含若干种类型的变量:内建的,字段或用户定义的

>>>变量不需要事先声明,所以awk需要根据上下文环境推断出变量的类型(字符串或数值)

 

内建变量

>>>内键变量可以简单理解是awk专属的环境变量,

变量

意义

默认值

ARGC

命令行参数的个数

-

ARGV

命令行参数数组

-

FILENAME

当前输入文件名

-

FNR

当前输入文件记录个数

-

FS

输入行字段分隔符

" "

NF

当前记录的字段个数

-

NR

到目前为止读的记录数量

-

OFMT

数值的输出格式

"%.6g"

OFS

输出字段分隔符

" "

ORS

输出的记录分隔符

"\n"

RLENGTH

被函数match匹配的字符串的长度

-

RS

控制着输入行的记录分隔符

"\n"

 

案例:ARGCARGV

需求:格式化输出文件date算出总数,并在每一行尾加上hello world两个字段,最后一行输出ARGCARGV

[bei@localhost test]$ cat date
Simon 96 97 99
Bei 92 100 95
Tom 100 92 97
Tim 80 99 99

[bei@localhost test]$ cat awk.sh
#!/bin/bash
awk 'BEGIN{
printf("%-10s%-10s%-10s%-10s%-10s\n","name","chinese","maths","english","total")
}
{
        total = $2 + $3 + $4
        printf("%-10s%-10.0f%-10.0f%-10.0f%-10.0f%-10s%-10s\n",$1,$2,$3,$4,total,a,b)
}
END{
print(ARGC,ARGV[0],ARGV[1],ARGV[2],ARGV[3])
}' a=hello b=world date 

[bei@localhost test]$ bash awk.sh
name      chinese   maths     english   total    
Simon     96        97        99        292       hello     world    
Bei       92        100       95        287       hello     world    
Tom       100       92        97        289       hello     world    
Tim       80        99        99        278       hello     world    
4 awk a=hello b=world date

说明:print(ARGC,ARGV[0],ARGV[1],ARGV[2],ARGV[3]) 对于这一行输出的理解

                            4         awk     a=hello    b=world    date

ARGC是命令行参数个数,除了自己定义的两个变量"a","b",还有一个参数存储程序名,一个参数存储文件名

ARGV[0],即第一个参数,表示awk程序的程序名,为"awk"这个字符串

ARGV[1],ARGV[2] ,表示属组中自己定义的第一个参数和第二个参数

ARGV[3],即最后一个参数,表示文件的文件名

 

 

字段变量

>>>对记录通过字段分隔符分隔后的一个个单元,即为字段,对字段进行引用即为字段变量

>>>字段变量可以用在算术或字符串运算中,也可以被赋值,即字段变量是可以修改的

 


 

④流程控制

>>>流程控制语句中,if-else用于决策,while、for、do用于循环

if-else语句

语法结构:

{

if (expression)

statements

else

statements

}

或者

{if (expression) statements;else statements}    

 

案例

[bei@localhost test]$ cat date
Simon 96 97 99
Bei 92 100 95
Tom 100 92 97
Tim 80 99 99

[bei@localhost test]$ cat control.awk
#!/bin/bash
{
        if ($2==100||$3==100||$4==100)
                print ( $1 " has a full score in subjects." )
        else
                print ( $1 " need to work hard." )
}

[bei@localhost test]$ awk -f control.awk date
Simon need to work hard.
Bei has a full score in subjects.
Tom has a full score in subjects.
Tim need to work hard.

 

 

while语句

语法结构:

{

while (expression)

{

statement1

statement2

……

}

}

或者

{while (expression) {statements;else statements}}

说明:

>>>在while循环中,expression被求值,如果expression的值为真则statements会被执行,然后expression再被求值,只要expression为真,循环就一直被执行下去

>>>每从输入流读取一行,while循环就会被执行

案例:对txt每行求和

[bei@localhost test]$ cat txt
1 2 1 2
2 3 2 5 3
3 2
4 3 2
1 1 2

[bei@localhost test]$ cat control.awk
{
        i=1
        sum=0
        while (i<=NF)
        {
                sum+=$i
                i++
        }
        print("line"NR,"Sum="sum)
}

[bei@localhost test]$ awk -f control.awk txt
line1 Sum=6
line2 Sum=15
line3 Sum=5
line4 Sum=9
line5 Sum=4

 

 

for语句    

语法结构:

{

for (expression1;expression2;expression3)

{

statement1;

statement2;

……

}

}

或者

{for (expression1;expression2;expression3) {statement1;statement2;statement3}}

expression1对变量初始化

expression2用来做条件判断

expression3用来做变量变化,例如自增自减

案例:对txt每行求和

[bei@localhost test]$ cat txt
1 2 1 2
2 3 2 5 3
3 2
4 3 2
1 1 2
[bei@localhost test]$ cat control.awk      
{
        sum=0
        for (i=1;i<=NF;i++)
        {
                sum+=$i
        }
        print("line"NR,"Sum="sum)
}
[bei@localhost test]$ awk -f control.awk txt
line1 Sum=6
line2 Sum=15
line3 Sum=5
line4 Sum=9
line5 Sum=4

 

 

do-while语句

语法结构:

{

do

{

statement1;

statement2;

……

}

while (expression)

}

或者

{do{statement1;statement2;……} while (expression)}

说明

>>>do-while语句与whilefor循环相比,它的测试条件在循环体底部,所以循环体至少会被执行一次

 

 

breakcontinue语句

>>>这两个语句用于影响循环的运行

>>>break会导致控制流马上从包围着它的循环内退出,循环包括while、for和do-while

>>>continue导致下一次迭代开始,即为提前进入当前循环的下一个轮循

break案例:只对txt文件,每行的前三个字段求和

[bei@localhost test]$ cat txt
1 2 1 2
2 3 2 5 3
3 2
4 3 2
1 1 2

[bei@localhost test]$ cat control.awk
{
        sum=0
        for (i=1;i<=NF;i++)
        {
                if (i>3)
                {
                        break
                }
                sum+=$i
        }
        print("line"NR,"Sum="sum)
}

[bei@localhost test]$ awk -f control.awk txt
line1 Sum=4
line2 Sum=7
line3 Sum=5
line4 Sum=9
line5 Sum=4

continue案例:只对txt文件,值小于3的字段求和

[bei@localhost test]$ cat txt
1 2 1 2
2 3 2 5 3
3 2
4 3 2
1 1 2

[bei@localhost test]$ cat control.awk      
{
        sum=0
        for (i=1;i<=NF;i++)
        {
                if ($i>=3)
                {
                        continue
                }
                sum+=$i
        }
        print("line"NR,"Sum="sum)
}

[bei@localhost test]$ awk -f control.awk txt
line1 Sum=6
line2 Sum=4
line3 Sum=2
line4 Sum=2
line5 Sum=4

 

 

exitnext语句

>>>next使得awk抓取下一个输入行

>>>exit会导致程序终止,如果END语句存在会执行END动作

 


 

⑤数组

>>>awk提供了一维数组,用于存放字符串与数值

>>>在awk中,数组可以称之为关联数组(association array,关联数组在数组下标index和元素value之间建立了一种关联

>>>数组与数组元素不需要事先声明,也不需要说明数组有多少个元素,即为无须定义并且可以直接使用,自动扩展

>>>awk的数组下标可以是字符串也可以是数值

例如:arrat[1]="bei"为数值下标;array["first"]="bei"为字符串下标

注意:因为1的字符串值与"1"是相同的,所以array[1]与array["1"]是同一个元素,但01和1的字符串值不相同

>>>如果下标使用的是字符串,一定要用双引号将字符串引起来,否则会把字符串当做一个未初始化过的变量(变量为空字符串),于是value会赋值到array[""]中

 

案例:使用数组倒序输出文件date

[bei@localhost test]$ cat date
IP1 1.1.1.1
IP2 192.168.1.1
IP3 172.168.1.1
[bei@localhost test]$ awk '{x[NR]=$0} END{for(i=NR;i>0;i--){print x[i]}}' date
IP3 172.168.1.1
IP2 192.168.1.1
IP1 1.1.1.1

说明:x[NR]=$0将行号作为index,行的内容作为value,建立关联数组x

             for(i=NR;i>0;i--){print x[i]},这是个for循环,用来遍历数组x,此时i=NR等于尾行的行号,即循环第一次输出的是尾行,然后i自减,遍历倒数第二行,以此循环,实现倒序输出

 

案例:将第一个字段相同的行的第二个字段累加作为value,赋值给下标为第一个字段的数组size

[bei@localhost test]$ cat txt
file 20
file 30
file 10
directory 14
directory 8
symbolic_link 4
symbolic_link 18

[bei@localhost test]$ cat array.awk
{
        size[$1]+=$2
}
END {
        for (i in size)
        {
                print (i,size[i])
        }
}

[bei@localhost test]$ awk -f array.awk txt
file 60
directory 22
symbolic_link 22

 

 

操作数组

>>>数组引用是如下所示的表达式:array[index]

       array即为数组的名称,index即为元素的索引,可以理解为下标

判断数组是否存在某个元素

>>>语法格式:index in array

>>>这个表达式用于测试特定索引是否存在,如果不存在不会产生创建该元素的副作用

if (2 in array)

print "Subscript 2 is present."

>>>但是以下方案会导致在数组array中创建array[2]:

if (array[2] != "")

print "Subscript 2 is present."

删除数组中的元素

>>>delete array[index]

 


 

⑥内建函数

 

内建算术函数

 

字符串函数

sub(regexp,replacement[,target])

>>>搜索taget中最左并且是最长的,能被regexp匹配的子字符串,使用replacement进行替换,返回替换发生的次数

>>>regexp为一个正则表达式,格式为/regexp/,需要用//

>>>target可以省缺,搜索匹配的对象是$0,即为输入流那一行的内容

>>>当replacement中有&符号,表示对regexp的反向引用,用来拼接使用

        (如果需要使用&这个字符,需要用两个转义符转义\\)

案例

[bei@localhost test]$ cat 1.txt
IP1 2.4 IP1
IP2 ccna IP2
IP3 chinanet IP3
IP4 chinanet IP4
#将第三个字段的IP替换成ip
[bei@localhost test]$ awk '{sub(/IP/,"ip",$3);print $0}' 1.txt
IP1 2.4 ip1
IP2 ccna ip2
IP3 chinanet ip3
IP4 chinanet ip4
#在replacement使用"&"对regexp反向引用,用来拼接使用
[bei@localhost test]$ awk '{sub(/IP/,"&v4_",$3);print $0}' 1.txt
IP1 2.4 IPv4_1
IP2 ccna IPv4_2
IP3 chinanet IPv4_3
IP4 chinanet IPv4_4

注意:replacement的字符串需要用双引号引起来,否则会将其当做变量使用

 

gsub(regexp,replacement[,target])

>>>g表示global,对输入流进行全局搜索替换,所有匹配到的内容都会被替换

 

 

gensub(regexp,replacementhow[,target])

>>>这个函数可以灵活控制去替换第几个被匹配到的字符

>>>how可以填充g或G表示全局匹配,也可以填充n表示替换匹配到的第n个

>>>gensub函数不会对原来的内容直接替换,而是需要将函数的结果赋值给变量,然后再对变量输出

        当需要使用时,需要对gensub函数进行赋值 a=gensub(regexp,replacement,how[,target]),然后再print a

>>>gensub函数支持使用括号来标记正则表达式regexp,然后在replacement使用"\\N"来反向引用括号内的内容

案例:将txt文件每行的第一个字段和第二个字段对换

[bei@localhost test]$ cat txt
file 20
file 30
file 10
directory 14
directory 8
symbolic_link 4
symbolic_link 18

[bei@localhost test]$ awk '{str=gensub(/(.+) (.+)/,"\\2 \\1","g",$0);print str}' txt
20 file
30 file
10 file
14 directory
8 directory
4 symbolic_link
18 symbolic_link

说明:/(.+) (.+)/匹配第一个字段和第二个字段

         "\\2 \\1"对匹配到的内容反向引用,\\1引用第一个()匹配的内容,\\2引用第二个()匹配到的内容

 

 

index(infind)

>>>返回字符串find在in中出现的位置,位置是指find字符串的第一个字符在in中出现的位置

如果没有找到,则函数的返回值为0

案例

[bei@localhost test]$ cat 1.txt
hello
world
haha
[bei@localhost test]$ awk '{ print ( index($0,"o") ) }' 1.txt
5
2
0

说明:通过index函数返回字符"o"在每一行出现的首个位置,如果没有则返回"0"

 

 

length([string])

>>>用于获取string中字符的数量,不是字段的数量

>>>如果是一个数值,则返回值为该数值的数字字符串的长度

>>>如果使用length计算不存在的变量,会报错

#字符串用单引号引起来作为变量abc

awk 'BEGIN { print length('abc') }'

0

#字符用双引号引起来作为字符串"abc"

awk 'BEGIN { print length("abc") }'

3

>>>如果string被省略,默认计算$0

 

 

match(string,regexp[,array])

>>>对string搜索,返回匹配到的内容在string中的位置

>>>匹配到的内容会被记录在array中,可以通过array[1]搜索

 

 

split(string,array[,fieldsep[,seps]])

>>>string是被切割的字符串

>>>array用来存储被切割后的字段

>>>fieldsep用来定义被切割的分隔符

>>>seps用来存储分隔符字符的数组

 

 

substr(string,start[,length])

>>>该函数作用是获取字符串,可以使用该函数进行字符串拼接,函数的返回值是获取的子字符串

>>>start表示从第几个字符开始,length表示获取的子字符串的长度

案例

[bei@localhost test]$ awk 'BEGIN{string="abcdefg";string=substr(string,1,2) "CDE" substr(string,6);print string}'

abCDEfg

说明:substr(string,1,2)获取函数第一个和第二个字符,substr(string,6)获取string从第六个字符以后的所有字符

猜你喜欢

转载自blog.csdn.net/Mr_Bei/article/details/83112860