1.打印某行到某行之间的内容
有个文件test的内容如下:
ert
fff
**
[abcfd]
123
324
444
[rty]
**
fgfgf
怎么能截取
[abcfd]
123
324
444
[rty]
这一部分出来呢?
答案: sed -n ‘/[abcfd]/,/[rty]/p’ test
2.sed转换大小写
sed中,使用\u表示大写,\l表示小写
把每个单词的第一个小写字母变大写:
sed ‘s/\b[a-z]/\u&/g’ filename把所有小写变大写:
sed ‘s/[a-z]/\u&/g’ filename大写变小写:
sed ‘s/[A-Z]/\l&/g’ filename
[root@linux7-128 ~]# cat test.txt
ert
fff
AAb
bbC
fgfgf
[root@linux7-128 ~]# sed 's/\b[a-z]/\u&/g' test.txt
Ert
Fff
AAb
BbC
Fgfgf
[root@linux7-128 ~]# sed 's/[a-z]/\u&/g' test.txt
ERT
FFF
AAB
BBC
FGFGF
[root@linux7-128 ~]# sed 's/[A-Z]/\l&/g' test.txt
ert
fff
aab
bbc
fgfgf
3.sed在某一行最后添加一个数字
sed 's/\(^a.*\)/\1 12/' test
在所有a开头的行后面添加一个数字12
[root@linux7-128 ~]# cat test.txt
askdj
aslkd aslkdjf3e
skdjfsdfj
sdkfjk
fsdkfjksdjfkjsdf
12sdfesdf
aslkdjfkasdjf asdlfkjaskdfj
[root@linux7-128 ~]# sed 's/\(^a.*\)/\1 12/' test.txt
askdj 12
aslkd aslkdjf3e 12
skdjfsdfj
sdkfjk
fsdkfjksdjfkjsdf
12sdfesdf
aslkdjfkasdjf asdlfkjaskdfj 12
4.sed删除某关键字的下一行到最后一行
[root@linux7-128 ~]# cat test.txt
a
bc
c
d
e
f
g
[root@linux7-128 ~]# sed '/c/{p;:a;N;$!ba;d}' test.txt
a
bc
定义一个标签a,匹配c,然后N把下一行加到模式空间里,匹配最后一行时,才退出标签循环,然后命令d,把这个模式空间里的内容全部清除。
if 匹配”c”
:a
追加下一行
if 不匹配”$”
goto a
最后退出循环,d命令删除。
由上,我们可以通过sed删除匹配行以及匹配行下一行
sed -i '/sample/{N;d}' filename
//sample是匹配字符,N在这里就是下一行,d是删除
[root@linux7-128 ~]# cat test.txt
agfh
bc
cdfgfd
dsde3e
e1qwsd
fcds
g
dfsd
[root@linux7-128 ~]# sed -i '/g/{N;d}' test.txt
[root@linux7-128 ~]# cat test.txt
e1qwsd
fcds
删除了含有g的行以及下一行
5.如何使用sed打印1到100行包含某个字符串的行
sed -n '1,100{/abc/p}' 1.txt
[root@linux7-128 ~]# cat test.txt
e1qwsd
fcds
sdef
dfre
f4rfdsf
fdsfwef
sferg
efdvreg
vreter
erftfv
hjhmh
khjmbnm
cvbrt
drygt
sdwrwes
geg
vx
rgedv
drgfcbgdr
cbrt
hbcb
rthy
etgdfb
[root@linux7-128 ~]# sed -n '1,100{/v/p}' test.txt
efdvreg
vreter
erftfv
cvbrt
vx
rgedv
[root@linux7-128 ~]# sed -n '1,100{/e/p}' test.txt
e1qwsd
sdef
dfre
fdsfwef
sferg
efdvreg
vreter
erftfv
sdwrwes
geg
rgedv
etgdfb
6.awk 中使用外部shell变量
如:
A=44echo “ABCD” | awk -v GET_A=$A ’{print GET_A}’
说明:-v选项用于定义参数,这里表示将变量A的值赋予GET_A。
有多少个变量需要赋值,就需要多少个-v选项。与之等价的:应用于脚本中:
#! /bin/bash
sort -n filename |awk -F ':' '{print $1}'|uniq >id.txt
for id in `cat id.txt`; do
echo "[$id]"
awk -v id2=$id -F ':' '$1==id2 {print $2}' filename // 另外的方式为: awk -F ':' '$1=="'id'" {print $2}' filename
done
附件:
cat filename
1111111:13443253456
2222222:13211222122
1111111:13643543544
3333333:12341243123
2222222:12123123123
运行脚本后结果为:
[1111111]
13443253456
13643543544
[2222222]
13211222122
12123123123
[3333333]
12341243123
这个不是很明白
7.awk 合并一个文件
我有这样的需求,需要把两个文件中,第一列相同的行合并到同一行中。举个例子,有两个文件,内容如下
cat 1.txt
1 aa
2 bb
3 ee
4 ss
cat 2.txt
1 ab
2 cd
3 ad
4 bd
5 de
合并后的结果为:
1 ab aa
2 cd bb
3 ad ee
4 bd ss
5 de
实现的命令为:
awk 'NR==FNR{a[$1]=$2}NR>FNR{print $0,a[$1]}' 1.txt 2.txt
[root@localhost ~]# awk 'NR==FNR{a[$1]=$2}NR>FNR{print $0,a[$1]}' 1.txt 2.txt
1 ab aa
2 cd bb
3 ad ee
4 bd ss
5 de
解释:NR表示读取的行数, FNR表示读取的当前行数,大家可以运行这个命令
awk '{print NR,FNR}' 1.txt 2.txt
,比较NR和FNR
所以其实NR==FNR 就表示读取1.txt的时候。 同理NR>FNR表示读取2.txt的时候
数组a其实就相当于一个map
8.把一个文件多行连接成一行
a=cat file
;echo $a
awk '{printf("%s ",$0)}' file // %s
后记得要有一空格,否则出来就是完全连在一起的,中间连空格都没有
cat file |xargs
应用举例:一个文件每行都有一个数字,现在需要把每行的数字用“+”连接起来。
[root@localhost ~]# cat 1.txt
96
1093
1855
1253
1364
1332
2308
2589
2531
1239
2164
2826
2787
2145
2617
4311
1810
2115
1235
[root@localhost ~]# awk '{printf ("%s+",$0)}' 1.txt; echo ""
96+1093+1855+1253+1364+1332+2308+2589+2531+1239+2164+2826+2787+2145+2617+4311+1810+2115+1235++
这里注意,最后一个是带“+”的。echo “” 的作用是换行。
另外的方法是
[root@localhost ~]# cat 1.txt|xargs|sed 's/ /+/g'
96+1093+1855+1253+1364+1332+2308+2589+2531+1239+2164+2826+2787+2145+2617+4311+1810+2115+1235
9.awk中gsub函数的使用
awk 'gsub(/www/,"abc")' /etc/passwd
// passwd文件中把所有www替换为abc
awk -F ':' 'gsub(/www/,"abc",$1) {print $0}' /etc/passwd
// 替换$1中的www为abc
10.awk 截取指定多个域为一行
用awk指定分隔符把文本分为若干段。如何把相同段的内容弄到一行?
以/etc/passwd为例,该文件以”:”作为分隔符,分为了7段。
for i in `seq 1 7`
do
awk -F ':' -v a=$i '{printf $a " "}' /etc/passwd
echo
done
11.grep 或 egrep 或awk 过滤两个或多个关键词
grep -E '123|abc' filename
// 找出文件(filename)中包含123或者包含abc的行
egrep '123|abc' filename
//用egrep同样可以实现
awk '/123|abc/' filename
// awk 的实现方式
12.用awk编写生成以下结构文件的程序
用awk编写生成以下结构文件的程序。( 最后列使用现在的时间,时间格式为YYYYMMDDHHMISS) 各列的值应如下所示,每增加一行便加1,共500万行。
1,1,0000000001,0000000001,0000000001,0000000001,0000000001,0000000001,2005100110101
2,2,0000000002,0000000002,0000000002,0000000002,0000000002,0000000002,2005100110101
用shell解决:
#! /bin/bash
for i in `seq 1 5000000`; do
n=`echo "$i"|awk '{print length($0)}'`
export m=$[10-$n]
export o=`perl -e '$a='0'; $b=$a x $ENV{"m"}; print $b;'`
export j=$i
p=`perl -e '$c=$ENV{"o"}.$ENV{"j"}; print $c;'`
echo "$i,$i,$p,$p,$p,$p,$p,$p,`date +%Y%m%d%H%M%S`"
done
其中用到了perl,所以脚本整体看起来比较啰嗦,希望能找到更好的解决办法。
PS: shell 执行效率很低,so 该脚本运行时间会很漫长!
awk解决:
awk 'BEGIN{for(i=1;i<=10;i++)printf("%d,%d,%010d,%010d,%010d,%010d,%010d,%010d,%d\n",i,i,i,i,i,i,i,i,strftime("%Y%m%d%H%M%s"))}'
13.awk用print打印单引号
awk 'BEGIN{print "a'"'"'s"}'
//不用脱义,就多写几个单引号、双引号
awk 'BEGIN{print "a'\''s"}'
//用脱义,脱义的是单引号
awk 'BEGIN{print "a\"s"}'
//用脱义,脱义的是双引号
在awk中可以用\字符脱义的 ,
head -2 test.txt |awk '{print"aaa\"" $1}'
这是脱义双引号的
head -2 test.txt |awk '{print"11'\''" $1}'
脱义单引号
14.把两个文件中相同的行合并成一行
paste filename1 filename2
这样就可以实现了。举个例子。
cat a.txt
1 2 3
4 5 6
a b c
cat b.txt
3 2 1
6 5 4
c b a
则 paste a.txt b.txt
结果为
1 2 3 3 2 1
4 5 6 6 5 4
a b c c b a
如果,你想在两个文件连接处用一个指定的字符连接,还可以用-d来指定
paste -d '+' a.txt b.txt
结果为
1 2 3+3 2 1
4 5 6+6 5 4
a b c+c b a
15.awk的流程控制BEGIN和END
#cat password
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
haldaemon:x:68:68:HAL daemon:/:/sbin/nologin
root:x:0:0:root:/root:/bin/bash
mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/bash
root:x:0:0:root:/root:/bin/bash
#awk '/root/{count++;}{print "root was found "count" times"}' /mnt/passwd
root was found 1 times
root was found 1 times
root was found 2 times
root was found 2 times
root was found 3 times
root was found 3 times
root was found 4 times
# awk '/root/{count++;}END{print "root was found "count" times"}' /mnt/passwd
root was found 4 times
BEGIN模块后紧跟着动作块,这个动作块在awk处理任何输入文件之前执行。所以它可以在没有任何输入的情况下进行测试。它通常用来改变内建变量的值,如OFS,RS和FS等,以及打印标题。如:$ awk‘BEGIN{FS=”:”; OFS=”\t”; ORS=”\n\n”}{print $1,$2,$3} test
。上式表示,在处理输入文件以前,域分隔符(FS)被设为冒号,输出文件分隔符(OFS)被设置为制表符,输出记录分隔符(ORS)被设置为两个换行符。$ awk ‘BEGIN{print “TITLE TEST”}只打印标题.
END不匹配任何的输入文件,但是执行动作块中的所有动作,它在整个输入文件处理完成后被执行。如$ awk ‘END{print “The number of records is” NR}’ test,上式将打印所有被处理的记录数。
如何把一行竖排的数据转换成横排?
awk ‘{printf(“%s,”,$1)}’ filename
awk ‘BEGIN {FS=”:”;OFS=”:”} gsub(/root/,”hwl”,$1) {print $0}’ passwd 作用于域t
awk ‘BEGIN {FS=”:”;OFS=”:”} gsub(/root/,”hwl”) {print $0}’ passwd 作用于全部域
awk ‘BEGIN {FS=”:”;OFS=”:”} sub(/root/,”hwl”,$6) {print $0}’ passwd 将t中第一次出现的r替换为s
在Unix awk中两个特别的表达式,BEGIN和END,这两者都可用于pattern中(参考前面的awk语法),提供BEGIN和END的作用是给程序赋予初始状态和在程序结束之后执行一些扫尾的工作。
任何在BEGIN之后列出的操作(在{}内)将在Unix awk开始扫描输入之前执行,而END之后列出的操作将在扫描完全部的输入之后执行。因此,通常使用BEGIN来显示变量和预置(初始化)变量,使用END来输出最终结果。
例:累计销售文件xs中的销售金额(假设销售金额在记录的第三字段):
cat sx
一:50件:200.00
二:60件:300.00
三:70件:400.00
$awk
'BEGIN { FS=":";print "统计销售金额";total=0}
{print $3;total=total+$3;}
END {printf "销售金额总计:%.2f",total}' sx
统计销售金额
200.00
300.00
400.00
销售金额总计:900.00
(注:>是shell提供的第二提示符,如要在shell程序Unix awk语句和Unix awk语言中换行,则需在行尾加反斜杠)
在这里,BEGIN预置了内部变量FS(字段分隔符)和自定义变量total,同时在扫描之前显示出输出行头。而END则在扫描完成后打印出总合计。
# awk 'BEGIN { FS=":";print "统计销售金额";total=0} {print $3;total=total+$3;}{printf "销售金额总计:%.2f",total}' sx
统计销售金额
200.00
销售金额总计:200.00300.00 //200+0 300
销售金额总计:500.00400.00 //200+300 400
销售金额总计:900.00 //500+400
================================
包含BEGIN模式和END模式的脚本awkscript:
#!/usr/bin/awk -f
-f参数告诉awk将该文件作为awk的程序文件,然后即可运行该程序。
# awk script using pipes -- awkscript
#1- 第一部分BEGIN会先执行,在输入文件之前执行
BEGIN{
printf " %-22s%s ", "NAME", "DISTRICT"
print "--------------------------------------"
}
#-1
#2- 第二部分 awk脚本正文,要对来自输入文件datafile的每一行都要执行一遍
/west/{count++}
{printf "%s %s %-15s ", $3, $4, $1| "sort +1" }
#-2
#3- 第三部分 输入文件关闭后awk退出之前执行
END{
close "sort +1"
printf "The number of sales persons in the western "
printf "region is " count "."
}
=================
awk 'BEGIN { OFS="%"}{print $1,$2}' file 通过设置输出分隔符(OFS="%")修改输出格式。
15.awk 用法(使用入门)
http://www.cnblogs.com/emanlee/p/3327576.html