lisi
13012345678
ls@21cn.com
要处理这个文件,可以将每三行看作是一个独立的记录,一个记录包含三个字段。如下脚本将原记录由三行转换成一行输出:
BEGIN {
FS=“\n”
RS=“”
}
{
print $1 ", " $2 ", " $3
}
此代码将产生以下输出:
zhangsan, 13712345678, zhs@hotmail.com
lisi, 13012345678, ls@21cn.com
在上面例子中,为了在三个字段之间插入一个逗号和空格,使用了",“。这个方法虽然有用,但比较难看。其实我们还有更好的方法,那就是设置变量OFS(输出字段分隔符)。OFS缺省情况下被设置成” "(单个空格)。使用如下脚本可以达到上面例子同样的效果:
BEGIN {
FS=“\n”
RS=“”
OFS=", "
}
{
print $1, $2, $3
}
awk还有一个特殊变量ORS(输出记录分隔符)。ORS缺省情况下被设置成\n
,如果我们将其设为\n\n
,就可以使输出记录的间隔翻倍。例子就不举了,大家可以自己试试。个空格分隔记录(而不换行),将ORS设置成 (空格)。
需要注意的是,使用上面的方法,最多只能处理一个记录占用三行的文本,象下面一个记录占据四行的通讯录,就处理不了了(大家可以试试看):
wangwu
13512345678
ww@163.com
wuhan, hubei
要处理这种情况,代码最好考虑每个记录的字段数量,并依次打印每个记录。以下就是修正的代码:
BEGIN {
FS=“\n”
RS=“”
ORS=“”
}
{
x=1
while ( x<NF ) {
print $x “\t”
x++
}
print $NF “\n”
}
程序输出如下:
wangwu 13512345678 ww@163.com wuhan, hubei
awk的if语句类似于C语言的if语句,没什么好说的,举一个例子吧:
{
if ( $1 == “foo” ) {
if ( $2 == “foo” ) {
print “uno”
} else {
print “one”
}
} else if ($1 == “bar” ) {
print “two”
} else {
print “three”
}
}
其实在第1节的最后(处理多行),我们已经看到了awk的while循环结构,它等同于相应的C语言while循环。awk还有"do…while"循环,它在代码块结尾处对条件求值,还是直接举例吧:
do...while
示例
{
count=1
do {
print “I get printed at least once no matter what”
} while ( count != 1 )
}
for
循环
也等同于C语言的for循环:
for ( x = 1; x <= 4; x++ ) {
print “iteration”,x
}
break
和continue
此外,如同C语言一样,awk提供了break、continue来控制awk的循环结构。break语句用于跳出最深层的循环,使循环立即终止,并继续执行循环代码块后面的语句。continue语句使awk立即开始执行下一个循环迭代,而不执行代码块的其余部分。
在awk中,数组下标通常从1开始,而不是0:
myarray[1]=“jim”
myarray[2]=456
awk遇到第一个赋值语句时,它将创建myarray,并将元素myarray[1]设置成"jim"。执行了第二个赋值语句后,数组就有两个元素了。Awk数组不需要连续的数字序列下标(例如,可以定义myarr[1]和myarr[1000],但不定义其它所有元素)
awk可以使用in
操作来遍历数组中的所有元素,如下所示:
for ( x in myarray ) {
print myarray[x]
}
但是这个方法有一个缺点——当awk在数组下标之间轮转时,它不会依照任何特定的顺序。那就意味着我们不能知道以上代码的输出是:
jim
456
还是
456
jim
awk数组中还可以使用字符串下标,其实,不管你使用的下标是字符串还是数字,awk在幕后还将其认为是字符串下标。举例如下:
代码一:
myarr[“1”]=“China”
print myarr[“1”]
代码二:
myarr[“1”]=“Mr. Whipple”
print myarr[1]
代码三:
myarr[“name”]=“Mr. Whipple”
print myarr[“name”]
它们都将打印 “China”!
删除数组元素使用delete
,举例如下:
delete fooarray[1]
另外,如果想要查看是否存在某个特定数组元素,可以使用特殊的in
布尔运算符,如下所示:
if ( 1 in fooarray ) {
print “It’s there.”
} else {
print “Can’t find it.”
}
========================================================================
虽然大多数情况下awk的print语句可以完成任务,但有时我们还需要更多。使用两个函数printf()
、sprintf()
,将能让输出锦上添花。printf()
会将格式化字符串打印到stdout
,而sprintf()
则返回可以赋值给变量的格式化字符串。
从下面例子可以看到,它们几乎与C语言完全相同。
x=1
b=“foo”
printf(“%s got a %d on the last test\n”,“Jim”,83)
myout=(“%s-%d”,b,x)
print myout
此代码将打印:
Jim got a 83 on the last test
foo-1
既然awk把所有变量都当作字符串处理,那么字符串处理对awk就显得尤为重要。但要说明一点,awk不能象在其它语言(如 C、C++)中那样将字符串看作是字符数组。例如,如果执行以下代码:
mystring=“How are you doing today?”
print mystring[3]
将会接收到一个错误,如下所示:
awk: string.gawk:59: fatal: attempt to use scalar as array
不用担心,awk有许多字符串函数,弥补了这个缺陷。现将常用的字符串函数列举如下:
函数使用方式如:
从文件中找出长度大于 20 的行
[root@ccx ccx]# awk ‘length>20’ test.txt
good things are about to happen
我感到难过,不是因为你欺骗了我,而是因为我再也不能相信你了,555
[root@ccx ccx]#
| 字符串函数 | 描述 |
| — | — |
| length()
| 返回字符串的长度 |
| index()
| 返回子字符串在另一个字符串中出现的位置 |
| tolower()
| 返回字符串并且将所有字符转换成小写 |
| toupper()
| 返回字符串并且将所有字符转换成大写 |
| substr()
| 返回从字符串中选择的子串 |
| match()
| 返回子字符串在另一个字符串中出现的位置。它与index()的区别在于它并不搜索子串,它搜索的是正则表达式。 |
| sub()
| 替换匹配的第一个字符序列,并返回整个字符串 |
| substr()
| 使用substr()
可以从字符串中选择子串。以下是substr()
的调用方法:mysub=substr(mystring,startpos,maxlen)
,以下是一个示例:print substr(mystring,9,3)
|
| gsub()
| 替换匹配的全部字符序列,并返回整个字符串 |
| split()
| 分割字符串,并将各部分放到使用整数下标的数组中 |
| length()
| 返回字符串的长度,例子如:print length(mystring)
|
| index()
| 返回子字符串在另一个字符串中出现的位置,如果没有找到该字符串则返回0,例子如:print index(mystring,"you")
|
| tolower()
和toupper()
| 返回字符串并且将所有字符分别转换成小写或大写。注意,tolower()
和toupper()
返回新的字符串,不会修改原来的字符串。例子:print tolower(mystring)
,print toupper(mystring)
|
| match()
| match()
与index()
非常相似,它与index()
的区别在于它并不搜索子串,它搜索的是正则表达式。match()
函数将返回匹配的起始位置,如果没有找到匹配,则返回0。此外,match()
还将设置两个变量,叫作RSTART
和RLENGTH
。RSTART
包含返回值(第一个匹配的位置),RLENGTH
指定它占据的字符跨度(如果没有找到匹配,则返回-1)。通过使用RSTART
、RLENGTH
、substr()
和一个小循环,可以轻松地遍历字符串中的每个匹配。以下是一个match()
调用示例:print match(mystring,/you/)
,RSTART
, RLENGTH
|
| gsub()
| |
注:
sub()
和gsub()
是两个字符串替换函数。sub()
的调用方法如下:
sub(regexp,replstring,mystring)
调用sub()
时,它将在mystring
中匹配regexp
的第一个字符序列,并且用replstring
替换该序列。gsub()
与sub()
的唯一的区别是sub()
替换第一个regexp
匹配(如果有的话),gsub()
则执行全局替换,换出字符串中的所有匹配。举例如下:
sub(/o/,“O”,mystring)
print mystring
mystring=“How are you doing today?”
gsub(/o/,“O”,mystring)
print mystring
其输出结果如下:
HOw are you doing today?
HOw are yOu dOing tOday?
split()
的功能是分割字符串,并将分割后的各部分放到使用整数下标的数组中。此函数有三个变量,第一个自变量为要分割的原始字符串,第二个自变量为分割后填入的数组名称,第三个变素为用于指示分割的分隔符。split()
返回时,它将返回分割的字符串元素的数量。split()
将分割的每一个部分赋值给下标从1开始的数组。举例如下:
numelements=split(“Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec”,mymonths,“,”)
print mymonths[1],mymonths[numelements]
其输出如下:
Jan Dec
最后需要说明一点的是,调用length()
、sub()
或gsub()
时,可以去掉最后一个变量,这样awk将对$0
(整个当前行)应用函数调用。例如要打印文件中每一行的长度,使用以下awk脚本:
{
print length()
}
=====================================================================
- 格式:
awk -f name.awk test.txt
test.txt
内容如下
[root@ccx ccx]# cat test.txt
this is a test
good things are about to happen
我感到难过,不是因为你欺骗了我,而是因为我再也不能相信你了,555
[root@ccx ccx]#
awk脚本名:test.awk
内容如下
[root@ccx ccx]# cat test.awk
#!/bin/awk -f
#执行前
BEGIN{
FS=“[ ,]”
}
#执行中
{
print $1 , $2
}
#执行后
END{
print “test”
}
使用空格和,为分隔符,打印1和2个结果并在脚本最后输出test,执行结果如下:
[root@ccx ccx]# awk -f test.awk test.txt
this is
good things
我感到难过 不是因为你欺骗了我
test
[root@ccx ccx]#
test.txt文本内容如下
[root@ccx ccx]# cat test.txt
this is a test
good things are about to happen
[root@ccx ccx]#
可以用来过滤命令内容的,如果是脚本中,则每行的1和4行内容都会被打印:awk '{print $1,$4}'
[root@ccx ccx]# awk ‘{print $1,$4}’ test.txt
this test
good about
[root@ccx ccx]#
test.txt
内容如下
[root@ccx ccx]# cat test.txt
this is a test
good things are about to happen
我感到难过,不是因为你欺骗了我,而是因为我再也不能相信你了,555
[root@ccx ccx]#
使用单个","分割
注:这种情况如果一行中没有指定分割的内容,则会整行打印(如下,只有中文有,
,所以只有中文的$1和$2生效了。
[root@ccx ccx]# awk -F, ‘{print $1,$2}’ test.txt
this is a test
good things are about to happen
我感到难过 不是因为你欺骗了我
使用多个分隔符
先使用空格分割,然后对分割结果再使用","分割
注:使用多个分隔符需要在-F后面加上'[在这里面直接添加分隔符]'
[root@ccx ccx]# awk -F’[ ,]’ ‘{print $1,$2}’ test.txt
this is
good things
我感到难过 不是因为你欺骗了我
[root@ccx ccx]#
test.txt
内容如下
[root@ccx ccx]# cat test.txt
this is a test
good things are about to happen
我感到难过,不是因为你欺骗了我,而是因为我再也不能相信你了,555
[root@ccx ccx]#
- -v是设置变量,使用的时候直接在-v后面定义变量,不需要间隔符。
注:因为没有设置分隔符,所以默认分隔符是空格
。
[root@ccx ccx]# awk -va=1 ‘{print $1,$1+a}’ test.txt
this 1
good 1
_____________________________ 1
我感到难过,不是因为你欺骗了我,而是因为我再也不能相信你了,555 1
1
[root@ccx ccx]#
- 设置变量和分隔符为
,
如下
注,一行中没有,的则不会匹配的(如果需要都匹配,则设置多个分隔符)。
[root@ccx ccx]# awk -va=1 -F, ‘{print $1,$1+a}’ test.txt
this is a test 1
good things are about to happen 1
_____________________________ 1
我感到难过 1
1
[root@ccx ccx]#
test.txt
内容如下
[root@ccx ccx]# cat test.txt
this is a test
this not balabala
good things are about to happen
我感到难过,不是因为你欺骗了我,而是因为我再也不能相信你了,555
[root@ccx ccx]#
[root@ccx ccx]#
匹配字符t
.
是绝对匹配,没有匹配到的不会被打印,*
即使没有匹配到的也会被打印
[root@ccx ccx]# awk ‘/t./{print}’ test.txt
this is a test
good things are about to happen
[root@ccx ccx]# awk ‘/t*/{print}’ test.txt
this is a test
good things are about to happen
我感到难过,不是因为你欺骗了我,而是因为我再也不能相信你了,555
过滤第一列参数等于this的行
注:参数需要加上""
,否则过滤不出结果
[root@ccx ccx]# awk ‘$1==“this” {print}’ test.txt
this is a test
this not balabala
[root@ccx ccx]#
过滤第一列等于this并且第二列等于is的行
使用了&&
,注意:参数需要加上""
,否则过滤不出结果
[root@ccx ccx]# awk ‘$1==“this” && $2==“is” {print}’ test.txt
this is a test
[root@ccx ccx]#
输出第一列包含 th,并打印第一列与第四列
注:包含内容必须放//
中间,否则过滤无效。
[root@ccx ccx]# awk ‘$1 ~ /th/ {print $1,$4}’ test.txt
this test
this
[root@ccx ccx]#
输出包含 “is” 的行
~ 表示模式开始。// 中是模式。
[root@ccx ccx]# awk ‘/is/’ test.txt
this is a test
this not balabala
[root@ccx ccx]# more hosts
127.0.0.1 loopback localhost # loopback (lo0) name/address
172.30.126.10 IVM10
172.24.23.230 IVM230
172.24.23.80 IVM80
172.30.126.60 localhost
172.24.23.39 IVM39
172.24.23.82 IVM82
172.24.23.160 Robin_Hu_Dev
172.24.23.236 IVM236
[root@ccx ccx]# cat ./hosts | awk ‘{if($1 == ivm_ip && $2 == ivm_name) {print $0}}’ ivm_ip=172.24.23.39 ivm_name=IVM39
172.24.23.39 IVM39
[root@ccx ccx]# cat ./hosts | awk ‘{if($1 == ivm_ip || $2 == ivm_name) {print $0}}’ ivm_ip=172.24.23.39 ivm_name=IVM82
172.24.23.39 IVM39
172.24.23.82 IVM82
忽略大小写格式为: BEGIN{IGNORECASE=1} /忽略大小写的字母/
test.txt内容
[root@ccx ccx]# cat test.txt
this is a test
This not balabala
good things are about to happen
我感到难过,不是因为你欺骗了我,而是因为我再也不能相信你了,555
[root@ccx ccx]#
- 忽略this的大小写,默认打印全部
[root@ccx ccx]# awk 'BEGIN{IGNORECASE=1} /this/ ’ test.txt
this is a test
This not balabala
[root@ccx ccx]#
- 打印1和4行
[root@ccx ccx]# awk ‘BEGIN{IGNORECASE=1} /this/ {print $1,$4}’ test.txt
this test
This
[root@ccx ccx]#
打印第一列不是th的1和4内容
[root@ccx ccx]# awk ‘$1 !~ /th/ {print $1,$4}’ test.txt
This
good about
我感到难过,不是因为你欺骗了我,而是因为我再也不能相信你了,555
[root@ccx ccx]#
利用了字符串函数,更多函数见上面4.2。
[root@ccx ccx]# awk ‘length>20’ test.txt
good things are about to happen
我感到难过,不是因为你欺骗了我,而是因为我再也不能相信你了,555
[root@ccx ccx]#
直接±*/即可,方法如下:
[root@ccx ccx]# echo “2 5” | awk ‘{print($1+$2)}’
7
[root@ccx ccx]# echo “2 5” | awk ‘{print($1-$2)}’
-3
[root@ccx ccx]# echo “2 5” | awk ‘{print($1+$2)*$2}’
35
[root@ccx ccx]#
以:为分隔符,然后用for循环打印内容即可
[root@ccx ccx]# echo “123123123:1312312:sdfasdfsa” | awk -F":" ‘{for(i=1;i<=NF;i++) print $i}’
123123123
1312312
Sdfasdfsa
data.txt
内容如下
[root@ccx ccx]#cat data.txt
#CONTACT
ID=454
NAME=Fred Weinhaus
CREATED=1251770526
MAIL=fmw@alink.net
ICON=Contact0
#CONTACT
ID=455
NAME=binsos@googlegroups.com
CREATED=1253364946
MAIL=binsos@googlegroups.com
DESCRIPTION=
SHORT NAME=
PHONE=1xxxxx999901
ICON=Contact0
要求:::取name和 phone同时有效的,组成行。
awk -F[=] ‘BEGIN{i=0}$1==“#CONTACT”{i++}$1==“NAME”{n[i]=$2}$1==“PHONE”{p[i]=$2}END{for(i in n){if (n[i] && p[i]) printf “%s, %s\n”,n[i],p[i]}}’ data.txt
执行和结果如下
[root@ccx ccx]# awk -F[=] ‘BEGIN{i=0}$1==“#CONTACT”{i++}$1==“NAME”{n[i]=$2}$1==“PHONE”{p[i]=$2}END{for(i in n){if (n[i] && p[i]) printf “%s, %s\n”,n[i],p[i]}}’ data.txt
binsos@googlegroups.com, 1xxxxx999901
[root@ccx ccx]#
代码如下
seq 9 | sed ‘H;g’ | awk -v RS=‘’ ‘{for(i=1;i<=NF;i++)printf(“%dx%d=%d%s”, i, NR, i*NR, i==NR?“\n”:“\t”)}’
执行结果如下
[root@ccx ccx]# seq 9 | sed ‘H;g’ | awk -v RS=‘’ ‘{for(i=1;i<=NF;i++)printf(“%dx%d=%d%s”, i, NR, i*NR, i==NR?“\n”:“\t”)}’
1x1=1
1x2=2 2x2=4
1x3=3 2x3=6 3x3=9
1x4=4 2x4=8 3x4=12 4x4=16
1x5=5 2x5=10 3x5=15 4x5=20 5x5=25
1x6=6 2x6=12 3x6=18 4x6=24 5x6=30 6x6=36
1x7=7 2x7=14 3x7=21 4x7=28 5x7=35 6x7=42 7x7=49
1x8=8 2x8=16 3x8=24 4x8=32 5x8=40 6x8=48 7x8=56 8x8=64
1x9=9 2x9=18 3x9=27 4x9=36 5x9=45 6x9=54 7x9=63 8x9=72 9x9=81
[root@ccx ccx]#
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
in n){if (n[i] && p[i]) printf “%s, %s\n”,n[i],p[i]}}’ data.txt
binsos@googlegroups.com, 1xxxxx999901
[root@ccx ccx]#
代码如下
seq 9 | sed ‘H;g’ | awk -v RS=‘’ ‘{for(i=1;i<=NF;i++)printf(“%dx%d=%d%s”, i, NR, i*NR, i==NR?“\n”:“\t”)}’
执行结果如下
[root@ccx ccx]# seq 9 | sed ‘H;g’ | awk -v RS=‘’ ‘{for(i=1;i<=NF;i++)printf(“%dx%d=%d%s”, i, NR, i*NR, i==NR?“\n”:“\t”)}’
1x1=1
1x2=2 2x2=4
1x3=3 2x3=6 3x3=9
1x4=4 2x4=8 3x4=12 4x4=16
1x5=5 2x5=10 3x5=15 4x5=20 5x5=25
1x6=6 2x6=12 3x6=18 4x6=24 5x6=30 6x6=36
1x7=7 2x7=14 3x7=21 4x7=28 5x7=35 6x7=42 7x7=49
1x8=8 2x8=16 3x8=24 4x8=32 5x8=40 6x8=48 7x8=56 8x8=64
1x9=9 2x9=18 3x9=27 4x9=36 5x9=45 6x9=54 7x9=63 8x9=72 9x9=81
[root@ccx ccx]#
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-Zk178jWC-1715281094758)]
[外链图片转存中…(img-85vyS0Dq-1715281094759)]
[外链图片转存中…(img-gCERHBNJ-1715281094759)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!