上节讲了grep、sed工具,已经能满足常见的文本处理需求,但有些需求对于他们来说心有余而力不足,今天所讲的工具就能完成他们大多数的功能,它就是三剑客中的老大AWK,我相信一定不会让你失望,下面一起看看吧!
本章大纲:
8.3 awk
awk是一个处理文本的编程语言工具,能用简短的程序处理标准输入或文件、数据排序、计算以及生成报表等等。
在Linux系统下默认awk是gawk,它是awk的GNU版本。可以通过命令查看应用的版本:ls -l /bin/awk
基本的命令语法:awk option 'pattern {action}' file
其中pattern表示AWK在数据中查找的内容,而action是在找到匹配内容时所执行的一系列命令。花括号用于根据特定的模式对一系列指令进行分组。
awk处理的工作方式与数据库类似,支持对记录和字段处理,这也是grep和sed不能实现的。
在awk中,缺省的情况下将文本文件中的一行视为一个记录,逐行放到内存中处理,而将一行中的某一部分作为记录中的一个字段。用1,2,3...数字的方式顺序的表示行(记录)中的不同字段。用$后跟数字,引用对应的字段,以逗号分隔,0表示整个行。
8.3.1 选项
选项 |
描述 |
-f program-file |
从文件中读取awk程序源文件 |
-F fs |
指定fs为输入字段分隔符 |
-v var=value |
变量赋值 |
--posix |
兼容POSIX正则表达式 |
--dump-variables=[file] |
把awk命令时的全局变量写入文件, 默认文件是awkvars.out |
--profile=[file] |
格式化awk语句到文件,默认是awkprof.out |
8.3.2 模式
常用模式有:
Pattern |
Description |
BEGIN{ } |
给程序赋予初始状态,先执行的工作 |
END{ } |
程序结束之后执行的一些扫尾工作 |
/regular expression/ |
为每个输入记录匹配正则表达式 |
pattern && pattern |
逻辑and,满足两个模式 |
pattern || pattern |
逻辑or,满足其中一个模式 |
! pattern |
逻辑not,不满足模式 |
pattern1, pattern2 |
范围模式,匹配所有模式1的记录,直到匹配到模式2 |
而动作呢,就是下面所讲的print、流程控制、I/O语句等。
示例:
1)从文件读取awk程序处理文件
1
2
3
4
5
6
|
# vi test.awk {print$2} # tail -n3 /etc/services |awk -f test.awk 48049 /tcp 48128 /tcp 49000 /tcp |
2)指定分隔符,打印指定字段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
打印第二字段,默认以空格分隔: # tail -n3 /etc/services |awk '{print $2}' 48049 /tcp 48128 /tcp 48128 /udp 指定冒号为分隔符打印第一字段: # awk-F ':' '{print $1}' /etc/passwd root bin daemon adm lp sync ...... |
还可以指定多个分隔符,作为同一个分隔符处理:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
# tail -n3 /etc/services |awk -F'[/#]' '{print $3}' iqobject iqobject MatahariBroker # tail -n3 /etc/services |awk -F'[/#]' '{print $1}' iqobject 48619 iqobject 48619 matahari 49000 # tail -n3 /etc/services |awk -F'[/#]' '{print $2}' tcp udp tcp # tail -n3 /etc/services |awk -F'[/#]' '{print $3}' iqobject iqobject MatahariBroker # tail -n3 /etc/services |awk -F'[ /]+' '{print $2}' 48619 48619 49000 |
[]元字符的意思是符号其中任意一个字符,也就是说每遇到一个/或#时就分隔一个字段,当用多个分隔符时,就能更方面处理字段了。
3)变量赋值
1
2
3
4
5
6
7
8
9
|
# awk-v a=123 'BEGIN{print a}' 123 系统变量作为 awk 变量的值: #a=123 # awk-v a=$a 'BEGIN{print a}' 123 或使用单引号 # awk'BEGIN{print '$a'}' 123 |
4)输出awk全局变量到文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
# seq 5|awk --dump-variables '{print $0}' 1 2 3 4 5 # cat awkvars.out ARGC:number (1) ARGIND:number (0) ARGV:array, 1 elements BINMODE:number (0) CONVFMT:string ( "%.6g" ) ERRNO:number (0) FIELDWIDTHS:string ( "" ) FILENAME:string ( "-" ) FNR:number (5) FS:string ( " " ) IGNORECASE:number (0) LINT:number (0) NF:number (1) NR:number (5) OFMT:string ( "%.6g" ) OFS:string ( " " ) ORS:string ( "
" ) RLENGTH:number (0) RS:string ( "
" ) RSTART:number (0) RT:string ( "
" ) SUBSEP:string ( " 34" ) TEXTDOMAIN:string ( "messages" ) |
5)BEGIN和END
BEGIN模式是在处理文件之前执行该操作,常用于修改内置变量、变量赋值和打印输出的页眉或标题。
例如:打印页眉
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# tail /etc/services |awk 'BEGIN{print"Service Port Description
==="}{print $0}' Service Port Description === 3gpp-cbsp 48049 /tcp # 3GPP Cell Broadcast Service isnetserv 48128 /tcp # Image Systems Network Services isnetserv 48128 /udp # Image Systems Network Services blp5 48129 /tcp # Bloomberg locator blp5 48129 /udp # Bloomberg locator com-bardac-dw 48556 /tcp # com-bardac-dw com-bardac-dw 48556 /udp # com-bardac-dw iqobject 48619 /tcp #iqobject iqobject 48619 /udp # iqobject matahari 49000 /tcp # Matahari Broker |
END模式是在程序处理完才会执行。
例如:打印页尾
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# tail /etc/services |awk '{print $0}END{print "===
END......"}' 3gpp-cbsp 48049 /tcp # 3GPP Cell Broadcast Service isnetserv 48128 /tcp # Image Systems Network Services isnetserv 48128 /udp # Image Systems Network Services blp5 48129 /tcp # Bloomberg locator blp5 48129 /udp # Bloomberg locator com-bardac-dw 48556 /tcp # com-bardac-dw com-bardac-dw 48556 /udp # com-bardac-dw iqobject 48619 /tcp # iqobject iqobject 48619 /udp # iqobject matahari 49000 /tcp # Matahari Broker === END...... |
6)格式化输出awk命令到文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
# tail /etc/services |awk --profile 'BEGIN{print"Service Port Description
==="}{print $0}END{print"===
END......"}' Service Port Description === nimgtw 48003 /udp # Nimbus Gateway 3gpp-cbsp 48049 /tcp # 3GPP Cell Broadcast ServiceProtocol isnetserv 48128 /tcp # Image Systems Network Services isnetserv 48128 /udp # Image Systems Network Services blp5 48129 /tcp # Bloomberg locator blp5 48129 /udp # Bloomberg locator com-bardac-dw 48556 /tcp # com-bardac-dw com-bardac-dw 48556 /udp # com-bardac-dw iqobject 48619 /tcp # iqobject iqobject 48619 /udp # iqobject === END...... # cat awkprof.out # gawk profile, created Sat Jan 7 19:45:22 2017 # BEGIN block(s) BEGIN { print "Service Port Description
===" } # Rule(s) { print $0 } # END block(s) END { print "===
END......" } |
7)/re/正则匹配
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
匹配包含tcp的行: # tail /etc/services |awk '/tcp/{print $0}' 3gpp-cbsp 48049 /tcp # 3GPP Cell Broadcast Service isnetserv 48128 /tcp # Image Systems Network Services blp5 48129 /tcp # Bloomberg locator com-bardac-dw 48556 /tcp # com-bardac-dw iqobject 48619 /tcp # iqobject matahari 49000 /tcp # Matahari Broker 匹配开头是blp5的行: # tail /etc/services |awk '/^blp5/{print $0}' blp5 48129 /tcp # Bloomberg locator blp5 48129 /udp # Bloomberg locator 匹配第一个字段是8个字符的行: # tail /etc/services |awk '/^[a-z0-9]{8} /{print $0}' iqobject 48619 /tcp # iqobject iqobject 48619 /udp # iqobject matahari 49000 /tcp # Matahari Broker |
8)逻辑and、or和not
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
匹配记录中包含blp5和tcp的行: #tail /etc/services |awk '/blp5/ && /tcp/{print $0}' blp5 48129 /tcp # Bloomberg locator 匹配记录中包含blp5或tcp的行: #tail /etc/services |awk '/blp5/ || /tcp/{print $0}' 3gpp-cbsp 48049 /tcp # 3GPP Cell Broadcast Service isnetserv 48128 /tcp # Image Systems Network Services blp5 48129 /tcp # Bloomberg locator blp5 48129 /udp # Bloomberg locator com-bardac-dw 48556 /tcp # com-bardac-dw iqobject 48619 /tcp # iqobject matahari 49000 /tcp # Matahari Broker 不匹配开头是 #和空行: # awk'! /^#/ && ! /^$/{print $0}' /etc/httpd/conf/httpd.conf 或 # awk'! /^#|^$/' /etc/httpd/conf/httpd.conf 或 # awk'/^[^#]|"^$"/' /etc/httpd/conf/httpd.conf |
9)匹配范围
1
2
3
4
|
# tail /etc/services |awk '/^blp5/,/^com/' blp5 48129 /tcp # Bloomberg locator blp5 48129 /udp # Bloomberg locator com-bardac-dw 48556 /tcp # com-bardac-dw |
8.3.3 内置变量
变量名 |
描述 |
FS |
输入字段分隔符,默认是空格或制表符 |
OFS |
输出字段分隔符,默认是空格 |
RS |
输入记录分隔符,默认是换行符 |
ORS |
输出记录分隔符,默认是换行符 |
NF |
统计当前记录中字段个数 |
NR |
统计记录编号,每处理一行记录,编号就会+1 |
FNR |
统计记录编号,每处理一行记录,编号也会+1,与NR不同的是,处理第二个文件时,编号会重新计数。 |
ARGC |
命令行参数数量 |
ARGIND |
当前正在处理的文件索引值。第一个文件是1,第二个文件是2,以此类推 |
ARGV |
命令行参数数组序列数组,下标从0开始,ARGV[0]是awk |
ENVIRON |
当前系统的环境变量 |
FILENAME |
输出当前处理的文件名 |
IGNORECASE |
忽略大小写 |
SUBSEP |
数组中下标的分隔符,默认为" 34" |
示例:
1)FS和OFS
在程序开始前重新赋值FS变量,改变默认分隔符为冒号,与-F一样。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
# awk 'BEGIN{FS=":"}{print $1,$2}' /etc/passwd |head -n5 rootx bin x daemonx adm x lp x 也可以使用- v 来重新赋值这个变量: # awk -vFS=':' '{print $1,$2}' /etc/passwd |head -n5 # 中间逗号被换成了OFS的默认值 rootx bin x daemonx adm x lp x 由于OFS默认以空格分隔,反向引用多个字段分隔的也是空格,如果想指定输出分隔符这样: # awk 'BEGIN{FS=":";OFS=":"}{print $1,$2}' /etc/passwd |head -n5 root:x bin:x daemon:x adm:x lp:x 也可以通过字符串拼接实现分隔: # awk 'BEGIN{FS=":"}{print $1"#"$2}' /etc/passwd |head -n5 root #x bin #x daemon #x adm #x lp #x |
2)RS和ORS
RS默认是 分隔每行,如果想指定以某个字符作为分隔符来处理记录:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# echo "www.baidu.com/user/test.html" |awk'BEGIN{RS="/"}{print $0}' www.baidu.com user test .html RS也支持正则,简单演示下: # seq-f "str%02g" 10 |sed 'n;n;a-----' |awk 'BEGIN{RS="-+"}{print$1}' str01 str04 str07 str10 将输出的换行符替换为+号: # seq10 |awk 'BEGIN{ORS="+"}{print $0}' 1+2+3+4+5+6+7+8+9+10+ 替换某个字符: #tail -n2 /etc/services |awk 'BEGIN{RS="/";ORS="#"}{print$0}' iqobject 48619 #udp # iqobject matahari 49000 #tcp # Matahari Broker |
3)NF
NF是打印字段个数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# echo "a b c d e f" |awk '{print NF}' 6 打印最后一个字段: # echo "a b c d e f" |awk '{print $NF}' f 打印倒数第二个字段: # echo "a b c d e f" |awk '{print $(NF-1)}' e 排除最后两个字段: # echo "a b c d e f" |awk '{$NF="";$(NF-1)="";print$0}' a b cd 排除第一个字段: # echo "a b c d e f" |awk '{$1="";print $0}' bc d e f |
4)NR和FNR
NR统计记录编号,每处理一行记录,编号就会+1,FNR不同的是在统计第二个文件时会重新计数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
打印行数: # tail -n5 /etc/services |awk '{print NR,$0}' 1 com-bardac-dw 48556 /tcp # com-bardac-dw 2 com-bardac-dw 48556 /udp # com-bardac-dw 3 iqobject 48619 /tcp # iqobject 4 iqobject 48619 /udp # iqobject 5 matahari 49000 /tcp # Matahari Broker 打印总行数: # tail -n5 /etc/services |awk 'END{print NR}' 5 打印第三行: # tail -n5 /etc/services |awk 'NR==3' iqobject 48619 /tcp # iqobject 打印第三行第二个字段: # tail -n5 /etc/services |awk 'NR==3{print $2}' 48619 /tcp 打印前三行: # tail -n5 /etc/services |awk 'NR<=3{print NR,$0}' 1 com-bardac-dw 48556 /tcp # com-bardac-dw 2 com-bardac-dw 48556 /udp # com-bardac-dw 3 iqobject 48619 /tcp # iqobject |
看下NR和FNR的区别:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# cat a a b c # cat b c d e # awk'{print NR,FNR,$0}' a b 1 1 a 2 2 b 3 3 c 4 1 c 5 2 d 6 3 e |
可以看出NR每处理一行就会+1,而FNR在处理第二个文件时,编号重新计数。同时也知道awk处理两个文件时,是合并到一起处理。
1
2
3
4
5
6
7
|
# awk 'FNR==NR{print $0"1"}FNR!=NR{print $0"2"}' a b a1 b1 c1 c2 d2 e2 |
当FNR==NR时,说明在处理第一个文件内容,不等于时说明在处理第二个文件内容。
一般FNR在处理多个文件时会用到,下面会讲解。
5)ARGC和ARGV
ARGC是命令行参数数量
ARGV是将命令行参数存到数组,元素由ARGC指定,数组下标从0开始
1
2
3
4
5
6
7
8
|
# awk 'BEGIN{print ARGC}' 1 2 3 4 # awk 'BEGIN{print ARGV[0]}' awk # awk 'BEGIN{print ARGV[1]}' 1 2 1 # awk 'BEGIN{print ARGV[2]}' 1 2 2 |
6)ARGIND
ARGIND是当前正在处理的文件索引值,第一个文件是1,第二个文件是2,以此类推,从而可以通过这种方式判断正在处理哪个文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# awk '{print ARGIND,$0}' a b 1 a 1 b 1 c 2 c 2 d 2 e # awk 'ARGIND==1{print "a->"$0}ARGIND==2{print "b->"$0}'a b a->a a->b a->c b->c b->d b->e |
7)ENVIRON
ENVIRON调用系统变量。
1
2
3
4
5
6
7
8
|
# awk 'BEGIN{print ENVIRON["HOME"]}' /root 如果是设置的环境变量,还需要用 export 导入到系统变量才可以调用: # awk'BEGIN{print ENVIRON["a"]}' # export a # awk 'BEGIN{print ENVIRON["a"]}' 123 |
8)FILENAME
FILENAME是当前处理文件的文件名。
1
2
3
4
5
6
7
8
9
10
11
|
# awk 'FNR==NR{print FILENAME"->"$0}FNR!=NR{printFILENAME"->"$0}' a b a->a a->b a->c b->c b->d b->e 9)忽略大小写 # echo "A a b c" |xargs -n1 |awk 'BEGIN{IGNORECASE=1}/a/' A a |
等于1代表忽略大小写。
8.3.4 操作符
运算符 |
描述 |
(....) |
分组 |
$ |
字段引用 |
++ -- |
递增和递减 |
+ - ! |
加号,减号,和逻辑否定 |
* / % |
乘,除和取余 |
+ - |
加法,减法 |
| |& |
管道,用于getline,print和printf |
< > <= >= != == |
关系运算符 |
~ !~ |
正则表达式匹配,否定正则表达式匹配 |
in |
数组成员 |
&& || |
逻辑and,逻辑or |
?: |
简写条件表达式: expr1 ? expr2 : expr3 第一个表达式为真,执行expr2,否则执行expr3 |
= += -= *= /= %= ^= |
变量赋值运算符 |
须知:在awk中,有3种情况表达式为假:数字是0,空字符串和未定义的值
数值运算,未定义变量初始值为0。字符运算,未定义变量初始值为空。
举例测试:
1
2
3
4
5
6
|
# awk 'BEGIN{n=0;if(n)print"true";else print "false"}' false # awk'BEGIN{s="";if(s)print "true";else print"false"}' false # awk'BEGIN{if(s)print "true";else print "false"}' false |
示例:
1)截取整数
1
2
3
4
5
6
7
8
|
# echo "123abc abc123 123abc123"|xargs -n1 | awk '{print +$0}' 123 0 123 # echo "123abc abc123 123abc123"|xargs -n1 | awk '{print -$0}' -123 0 -123 |
2)感叹号
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
打印奇数行: # seq 6 |awk 'i=!i' 1 3 5 读取第一行,i是未定义变量,也就是i=!0,!取反意思。感叹号右边是个布尔值,0或空字符串为假,非0或非空字符串为真,!0就是真,因此i=1,条件为真打印当前记录。 没有print为什么会打印呢?因为模式后面没有动作,默认会打印整条记录。 读取第二行,因为上次i的值由0变成了1,此时就是i=!1,条件为假不打印。 读取第三行,上次条件又为假,i恢复初始值0,取反,继续打印。以此类推... 可以看出,运算时并没有判断行内容,而是利用布尔值真假判断输出当前行。 打印偶数行: # seq 6 |awk '!(i=!i)' 2 4 6 |
2)不匹配某行
1
2
3
4
5
6
7
8
|
# tail /etc/services |awk '!/blp5/{print$0}' 3gpp-cbsp 48049 /tcp # 3GPPCell Broadcast Service isnetserv 48128/tcp # Image Systems NetworkServices isnetserv 48128 /udp # ImageSystems Network Services com-bardac-dw 48556 /tcp # com-bardac-dw com-bardac-dw 48556 /udp # com-bardac-dw iqobject 48619 /tcp # iqobject iqobject 48619 /udp # iqobject matahari 49000 /tcp # MatahariBroker |
3)乘法和除法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
# seq 5 |awk '{print $0*2}' 2 4 6 8 10 # seq 5 |awk '{print $0%2}' 1 0 1 0 1 打印偶数行: # seq 5 |awk '$0%2==0{print $0}' 2 4 打印奇数行: # seq 5 |awk '$0%2!=0{print $0}' 1 3 5 |
4)管道符使用
1
2
3
4
5
6
|
# seq 5 |shuf |awk '{print$0|"sort"}' 1 2 3 4 5 |
5)正则表达式匹配
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# seq 5 |awk '$0~3{print $0}' 3 # seq 5 |awk '$0!~3{print $0}' 1 2 4 5 # seq 5 |awk '$0~/[34]/{print $0}' 3 4 # seq 5 |awk '$0!~/[34]/{print $0}' 1 2 5 # seq 5 |awk '$0~/[^34]/{print $0}' 1 2 5 |
6)判断数组成员
1
2
|
# awk'BEGIN{a["a"]=123}END{if("a" in a)print "yes"}'</dev/null yes |
7)三目运算符
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
# awk 'BEGIN{print1==1?"yes":"no"}' # 三目运算作为一个表达式,里面不允许写print yes # seq 3 |awk '{print$0==2?"yes":"no"}' no yes no 替换换行符为逗号: # seq 5 |awk '{printn=(n?n","$0:$0)}' 1 1,2 1,2,3 1,2,3,4 1,2,3,4,5 # seq 5 |awk'{n=(n?n","$0:$0)}END{print n}' 1,2,3,4,5 说明:读取第一行时,n没有变量,为假输出$0也就是1,并赋值变量n,读取第二行时,n是1为真,输出1,2 以此类推,后面会一直为真。 每三行后面添加新一行: # seq 10 |awk '{print NR%3?$0:$0"
txt"}' 1 2 3 txt 4 5 6 txt 7 8 9 txt 10 在 两行合并一行: # seq 6 |awk '{printf NR%2!=0?$0"":$0"
"}' 1 2 3 4 5 6 # seq 6 |awk 'ORS=NR%2?"":"
"' 1 2 3 4 5 6 # seq 6 |awk '{if(NR%2)ORS="";else ORS="
";print}' |
8)变量赋值
1
2
3
4
5
|
字段求和: # seq 5 |awk '{sum+=1}END{print sum}' 5 # seq 5 |awk '{sum+=$0}END{print sum}' 15 |
8.3.5 流程控制
1)if语句
格式:if(condition) statement [ else statement ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
单分支: # seq5 |awk '{if($0==3)print $0}' 3 双分支: # seq5 |awk '{if($0==3)print $0;else print "no"}' no no 3 no no 多分支: # catfile 1 2 3 4 5 6 7 8 9 # awk'{if($1==4){print "1"} else if($2==5){print "2"} elseif($3==6){print "3"} else {print "no"}}' file no 1 no |
2)while语句
格式:while(condition) statement
1
2
3
4
5
6
7
8
9
10
11
12
|
遍历打印所有字段: # awk'{i=1;while(i<=NF){print $i;i++}}' file 1 2 3 4 5 6 7 8 9 awk 是按行处理的,每次读取一行,并遍历打印每个字段。 |
3)for语句C语言风格
格式:for(expr1; expr2; expr3) statement
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
遍历打印所有字段: # catfile 1 2 3 4 5 6 7 8 9 # awk'{for(i=1;i<=NF;i++)print $i}' file 1 2 3 4 5 6 7 8 9 倒叙打印文本: # awk'{for(i=NF;i>=1;i--)print $i}' file 3 2 1 6 5 4 9 8 7 都换行了,这并不是我们要的结果。怎么改进呢? # awk'{for(i=NF;i>=1;i--){printf $i" "};print ""}' file # print本身就会新打印一行 3 2 1 6 5 4 9 8 7 或 # awk'{for(i=NF;i>=1;i--)if(i==1)printf $i"
";else printf $i""}' file 3 2 1 6 5 4 6 5 4 9 8 7 在这种情况下,是不是就排除第一行和倒数第一行呢?我们正序打印看下 排除第一行: # awk'{for(i=2;i<=NF;i++){printf $i" "};print ""}' file 2 3 5 6 8 9 排除第二行: # awk'{for(i=1;i<=NF-1;i++){printf $i" "};print ""}' file 1 2 4 5 7 8 IP加单引号: #echo '10.10.10.1 10.10.10.2 10.10.10.3' |awk '{for(i=1;i<=NF;i++)printf" 47"$i" 47"} '10.10.10.1' '10.10.10.2' '10.10.10.3'
|