# 打印以root开头或者nobody开头的行
➜ cat sed_example_1.sed
/^root/ p
/^nobody/ p
➜ sed -n -f sed_example_1.sed /etc/passwd
root:x:0:0:root:/root:/bin/zsh
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
语法3
格式: sed [options] -e {sed-command-1} -e {sed-command-2} {input-file}
例子:
# 打印以root开头或者nobody开头的行
➜ sed -n -e '/^root/ p' -e '/^nobody/ p' /etc/passwd
root:x:0:0:root:/root:/bin/zsh
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
#或者
➜ sed -n \
-e '/^root/ p' \
-e '/^nobody/ p' \
/etc/passwd
语法4
格式:
sed [options] '{
sed-command-1
sed-command-2
}' input-file
例子:
# 打印以root开头或者sync结尾的行
sed -n '{
/^root/ p
/nobody$/ p
}' /etc/passwd
root:x:0:0:root:/root:/bin/zsh
sync:x:4:65534:sync:/bin:/bin/sync
sed 流
利用 sed 流可以实现文件操作:
读
执行
打印
重复
源文件source.txt内容如下:
101,Ian Bicking,Mozilla
102,Hakim El Hattab,Whim
103,Paul Irish,Google
104,Addy Osmani,Google
105,Chris Wanstrath,Github
106,Mattt Thompson,Heroku
107,Ask Solem Hoel,VMware
范围
➜ sed -n '1~2 p' source.txt
# 从第1行开始,步长为2, 及奇数行
101,Ian Bicking,Mozilla
103,Paul Irish,Google
105,Chris Wanstrath,Github
107,Ask Solem Hoel,VMware ➜ sed -n '2~3 p' source.txt
# 从第2行开始,步长为3
102,Hakim El Hattab,Whim
105,Chris Wanstrath,Github
模式匹配
# 寻找包含Paul的行
➜ sed -n '/Paul/ p' source.txt
103,Paul Irish,Google
# 在第一行开始到第五行中, 从找到Paul开始打印到第五行
➜ sed -n '/Paul/,5 p' source.txt
103,Paul Irish,Google
104,Addy Osmani,Google
105,Chris Wanstrath,Github
# 从匹配Paul行打印达匹配Addy的行
➜ sed -n '/Paul/,/Addy/ p' source.txt
103,Paul Irish,Google
104,Addy Osmani,Google
# 匹配Paul行再多输出2行
➜ sed -n '/Paul/,+2 p' source.txt
103,Paul Irish,Google
104,Addy Osmani,Google
105,Chris Wanstrath,Github
删除行
# 删除所有行
➜ sed 'd' source.txt
(无输出)
# 只删除第二行
➜ sed '2 d' source.txt
...
# 删除第一到第四行
➜ sed '1,4 d' source.txt
105,Chris Wanstrath,Github
106,Mattt Thompson,Heroku
107,Ask Solem Hoel,VMware
# 删除奇数行
➜ sed '1~2 d' source.txt
102,Hakim El Hattab,Whim
104,Addy Osmani,Google
106,Mattt Thompson,Heroku
# 删除符合Paul到Addy的行
➜ sed '/Paul/,/Addy/d' source.txt
101,Ian Bicking,Mozilla
102,Hakim El Hattab,Whim
105,Chris Wanstrath,Github
106,Mattt Thompson,Heroku
107,Ask Solem Hoel,VMware
# 删除空行
➜ sed '/^$/ d' source.txt
# 删除用#注释的行
➜ sed '/^#/ d' source.txt
重定向
# 将source.txt内容重定向写到output.txt
➜ sed 'w output.txt' source.txt
# 和上面一样,但是没有在终端显示
➜ sed -n 'w output.txt' source.txt
# 只写第二行
➜ sed -n '2 w output.txt' source.txt
# 写一到四行到output.txt
➜ sed -n '1,4 w output.txt'
# 写匹配Ask的行到结尾行到output.txt
➜ sed -n '/Ask/,$ w output.txt'
替换
格式为:
sed '[address-range|pattern-range] s/original-string/replacement-string/[substitute-flags]' inputfile
例子:
# 替换Google为Github
➜ sed 's/Google/Github/' source.txt
101,Ian Bicking,Mozilla
102,Hakim El Hattab,Whim
103,Paul Irish,Github
104,Addy Osmani,Github
105,Chris Wanstrath,Github
106,Mattt Thompson,Heroku
107,Ask Solem Hoel,VMware
# 替换匹配Addy的行里面的Google为Github
➜ sed '/Addy/s/Google/Github/' source.txt
101,Ian Bicking,Mozilla
102,Hakim El Hattab,Whim
103,Paul Irish,Google
104,Addy Osmani,Github
105,Chris Wanstrath,Github
106,Mattt Thompson,Heroku
107,Ask Solem Hoel,VMware
# 默认s只会替换一行中的第一个匹配项
➜ sed '1s/a/A/' source.txt|head -1
101,IAn Bicking,Mozilla
# g可以替换每行的全部符合
➜ sed '1s/a/A/g' source.txt|head -1
101,IAn Bicking,MozillA
# 可以直接指定想要替换的第N个匹配项,这里是第二个
➜ sed '1s/a/A/2' source.txt|head -1
101,Ian Bicking,MozillA
# 使用w将能够替换的行重定向写到output.txt
➜ sed -n 's/Mozilla/Github/w output.txt' source.txt
➜ cat output.txt
101,Ian Bicking,Github
# 还可以使用i忽略匹配的大小写,看来freebsd的不能用
➜ sed '1s/iaN/IAN/i' source.txt|head -1
101,IAN Bicking,Mozilla
➜ cat files.txt
/etc/passwd
/etc/group
# 给每行前和后都添加点字符
➜ sed 's/\(.*\)/ls -l \1|head -1/' files.txt
ls -l /etc/passwd|head -1
ls -l /etc/group|head -1
# 用sed执行这个字符串命令
➜ sed 's/^/ls -l /e' files.txt
-rw-r--r-- 1 root root 1627 Oct 14 14:30 /etc/passwd
-rw-r--r-- 1 root root 807 Oct 14 14:30 /etc/group
# sed分隔符不只可以使用'/'
$sed 's|/usr/local/bin|/usr/bin|' path.txt
$sed 's^/usr/local/bin^/usr/bin^' path.txt
$sed 's@/usr/local/bin@/usr/bin@' path.txt
$sed 's!/usr/local/bin!/usr/bin!' path.txt
替换覆盖
➜ sed '{
s/Google/Github/
s/Git/git/
}' source.txt
101,Ian Bicking,Mozilla
102,Hakim El Hattab,Whim
103,Paul Irish,github
104,Addy Osmani,github
105,Chris Wanstrath,github
106,Mattt Thompson,Heroku
107,Ask Solem Hoel,VMware
& 代表匹配到的内容
➜ sed 's/^[0-9][0-9][0-9]/[&]/g' source.txt
[101],Ian Bicking,Mozilla
[102],Hakim El Hattab,Whim
[103],Paul Irish,Google
[104],Addy Osmani,Google
[105],Chris Wanstrath,Github
[106],Mattt Thompson,Heroku
[107],Ask Solem Hoel,VMware
➜ sed 's/^.*/[&]/' source.txt
[101,Ian Bicking,Mozilla]
[102,Hakim El Hattab,Whim]
[103,Paul Irish,Google]
[104,Addy Osmani,Google]
[105,Chris Wanstrath,Github]
[106,Mattt Thompson,Heroku]
[107,Ask Solem Hoel,VMware]
➜ sed 's/^.*/<<&>>/g' source.txt
<<101,Ian Bicking,Mozilla>>
<<102,Hakim El Hattab,Whim>>
<<103,Paul Irish,Google>>
<<104,Addy Osmani,Google>>
<<105,Chris Wanstrath,Github>>
<<106,Mattt Thompson,Heroku>>
<<107,Ask Solem Hoel,VMware>>
正则
# ^表示匹配以什么开头
➜ sed -n '/^101/ p' source.txt
101,Ian Bicking,Mozilla
# $表示匹配以什么结尾
➜ sed -n '/Github$/ p' source.txt
105,Chris Wanstrath,Github
# .表示单个字符,下面的匹配一个逗号然后I然后2个单字符
➜ sed -n '/,I../ p' source.txt
101,Ian Bicking,Mozilla
# *表示匹配0个或者多个, \+表示匹配一个或者多个, \?表示匹配0个或者1个
# [0-9]表示匹配数字,下面匹配包含3或者4的行
➜ sed -n '/[34]/ p ' source.txt
103,Paul Irish,Google
104,Addy Osmani,Google
# -表示范围,这里匹配3,4,5
➜ sed -n '/[3-5]/ p ' source.txt
103,Paul Irish,Google
104,Addy Osmani,Google
105,Chris Wanstrath,Github
# |表示或者的关系
➜ sed -n '/102\|103/ p ' source.txt
102,Hakim El Hattab,Whim
103,Paul Irish,Google
➜ cat numbers.txt
1
12
123
1234
12345
123456
# {m} 表示前面的匹配的重复次数
➜ sed -n '/^[0-9]\{5\}$/ p' numbers.txt
12345
# {m,n} 表示匹配m-n的次数都算
sed -n '/^[0-9]\{3,5\}$/ p' numbers.txt
123
1234
12345
# 删除所有注释行和空行
➜ sed -e 's/#.*//' -e '/^$/ d' /etc/profile
# 转化windows文件到unix格式
➜ sed 's/.$//' filename
#\1表示第一个正则匹配到的数据
➜ sed 's/\([^,]*\).*/\1/g' source.txt |head -1
101
#给每个单词第一个字母加括号
➜ echo "Dong Wei Ming" | sed 's/\(\b[A-Z]\)/\(\1\)/g'
(D)ong (W)ei (M)ing
➜ sed 's/\(^\|[^0-9.]\)\([0-9]\+\)\([0-9]\{3\}\)/\1\2,\3/g' numbers.txt
1
12
123
1,234
12,345
123,456
# 只取第一和第三列,并且换了他们的位置
$sed 's/\([^,]*\),\([^,]*\),\([^,]*\).*/\3,\1/g' source.txt
Mozilla,101
Whim,102
Google,103
Google,104
Github,105
Heroku,106
VMware,107
其他
# \l能将后面的一个字符变成小写
➜ sed 's/Ian/IAN/' source.txt|head -1
101,IAN Bicking,Mozilla
➜ sed 's/Ian/IA\lN/' source.txt|head -1
101,IAn Bicking,Mozilla
# \L能将后面的字符都变成小写
➜ sed 's/Ian/I\LAN/' source.txt|head -1
101,Ian Bicking,Mozilla
# \u能将后面的一个字符变成大写
➜ sed 's/Ian/IA\un/' source.txt|head -1
101,IAN Bicking,Mozilla
# \U能将后面的字都变成大写
➜ sed 's/Ian/\Uian/' source.txt|head -1
101,IAN Bicking,Mozilla
# \E能打断\L或者\U改变大小写
➜ sed 's/Ian/\Uia\En/' source.txt|head -1
101,IAn Bicking,Mozilla
# 使用以上功能:调换前2列,把名字列全部大写,公司列全部小写
➜ sed 's/\([^,]*\),\([^,]*\),\(.*\).*/\U\2\E,\1,\L\3/g' source.txt
IAN BICKING,101,mozilla
HAKIM EL HATTAB,102,whim
PAUL IRISH,103,google
ADDY OSMANI,104,google
CHRIS WANSTRATH,105,github
MATTT THOMPSON,106,heroku
ASK SOLEM HOEL,107,vmware
sed 可执行脚本
➜ cat testscript.sed
#!/bin/sed -nf
/root/ p
/nobody/ p
➜ chmod u+x testscript.sed
➜ ./testscript.sed /etc/passwd
root:x:0:0:root:/root:/bin/zsh
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
sed 修改源文件和备份
#-i会修改源文件,但是可以同时使用bak备份
➜ sed -i.bak 's/Ian/IAN/' source.txt
# or
➜ sed --in-place=.bak 's/Ian/IAN/' source.txt
# 这样备份一个修改前的文件为source.txt.bak
行后增加和行前插入
语法格式:
行后增加:sed '[address] a the-line-to-append' input-file
行前插入:sed '[address] i the-line-to-insert' input-file
例子:
➜ sed '2 a 108,Donald Stufft, Nebula' source.txt
101,IAN Bicking,Mozilla
102,Hakim El Hattab,Whim
108,Donald Stufft, Nebula
103,Paul Irish,Google
104,Addy Osmani,Google
105,Chris Wanstrath,Github
106,Mattt Thompson,Heroku
107,Ask Solem Hoel,VMware
➜ sed '2 i 108,Donald Stufft, Nebula' source.txt
101,IAN Bicking,Mozilla
108,Donald Stufft, Nebula
102,Hakim El Hattab,Whim
103,Paul Irish,Google
104,Addy Osmani,Google
105,Chris Wanstrath,Github
106,Mattt Thompson,Heroku
107,Ask Solem Hoel,VMware
修改行
格式:sed '[address] c the-line-to-insert' input-file
例子:
# 修改含有Paul的行
➜ sed '/Paul/ c 108,Donald Stufft, Nebula' source.txt
101,IAN Bicking,Mozilla
102,Hakim El Hattab,Whim
108,Donald Stufft, Nebula
104,Addy Osmani,Google
105,Chris Wanstrath,Github
106,Mattt Thompson,Heroku
107,Ask Solem Hoel,VMware
其他用法:
# = 可以显示行号
➜ sed = source.txt
1
101,Ian Bicking,Mozilla
2
102,Hakim El Hattab,Whim
3
103,Paul Irish,Google
4
104,Addy Osmani,Google
5
105,Chris Wanstrath,Github
6
106,Mattt Thompson,Heroku
7
107,Ask Solem Hoel,VMware
# y或翻译你要转换的字符,这里I会转化成i,B转换成b
➜ sed 'y/IB/ib/' source.txt |head -1
101,iAN bicking,Mozilla
# 默认print就是打印文件全文到终端
➜ awk '{print}' source.txt
101,Ian Bicking,Mozilla
102,Hakim El Hattab,Whim
103,Paul Irish,Google
104,Addy Osmani,Google
105,Chris Wanstrath,Github
106,Mattt Thompson,Heroku
107,Ask Solem Hoel,VMware
# 下面是通过,分割, 输出第二段。$0表示全行,类似shell用法
$awk -F ',' '{print $2}' source.txt
Ian Bicking
Hakim El Hattab
Paul Irish
Addy Osmani
Chris Wanstrath
Mattt Thompson
Ask Solem Hoel
# or
$awk -F "," '{print $2}' source.txt
$awk -F, '{print $2}' source.txt
# 一个格式化更好看些的效果
➜ awk -F "," 'BEGIN {print "--------------\nName\tComp\n--------------"} \
{print $2,"\t",$3}\
END {print "--------------"}' source.txt
--------------
Name Comp
--------------
Ian Bicking Mozilla
Hakim El Hattab Whim
Paul Irish Google
Addy Osmani Google
Chris Wanstrath Github
Mattt Thompson Heroku
Ask Solem Hoel VMware
--------------
模式匹配
# 用逗号做分隔符, 打印第二和第三列
➜ awk -F ',' '/Whim/ {print $2, $3}' source.txt
Hakim El Hattab Whim
# 可以加点格式化语句
➜ awk -F, '/Whim/ {print "Whim\"s full name:",$2}' source.txt
Whim"s full name: Hakim El Hattab
awk内置变量
1. FS:输入字段分隔符
设置分隔符:输入字段分隔符FS
➜ awk -F, '{print $2,$3}' source.txt
Ian Bicking Mozilla
Hakim El Hattab Whim
Paul Irish Google
Addy Osmani Google
Chris Wanstrath Github
Mattt Thompson Heroku
Ask Solem Hoel VMware
# 可以使用内置的FS - 输入字段分隔符 实现相同的功能
➜awk 'BEGIN {FS=","} {print $2,$3}' source.txt
Ian Bicking Mozilla
Hakim El Hattab Whim
Paul Irish Google
Addy Osmani Google
Chris Wanstrath Github
Mattt Thompson Heroku
Ask Solem Hoel VMware
➜ cat source-multiple-fs.txt
101,Ian Bicking:Mozilla%
102,Hakim El Hattab:Whim%
103,Paul Irish:Google%
104,Addy Osmani:Google%
105,Chris Wanstrath:Github%
106,Mattt Thompson:Heroku%
107,Ask Solem Hoel:VMware%
# 发现上面的分隔符有三种:逗号分号和百分号,这样就可以这样使用:
➜ awk 'BEGIN {FS="[,:%]"} {print $2,$3}' source-multiple-fs.txt
Ian Bicking Mozilla
Hakim El Hattab Whim
Paul Irish Google
Addy Osmani Google
Chris Wanstrath Github
Mattt Thompson Heroku
Ask Solem Hoel VMware
2. OFS:输出字段分隔符
设置输出时的分隔符:输出字段分隔符OFS
➜ awk -F, '{print $2":"$3}' source.txt
Ian Bicking:Mozilla
Hakim El Hattab:Whim
Paul Irish:Google
Addy Osmani:Google
Chris Wanstrath:Github
Mattt Thompson:Heroku
Ask Solem Hoel:VMware
➜ awk -F, 'BEGIN {OFS=":"} {print $2":"$3}' source.txt
Ian Bicking:Mozilla
Hakim El Hattab:Whim
Paul Irish:Google
Addy Osmani:Google
Chris Wanstrath:Github
Mattt Thompson:Heroku
Ask Solem Hoel:VMware
3. RS:输入记录分隔符
现在有一个文件 source-one-line.txt 内容为:
1,one:2,two:3,three:4,four
想输出
one
two
这样的效果。
借用记录分隔符 RS,先把单行内容分割,然后再按 -F 分割输出:
awk -F, 'BEGIN {RS=":"} {print $2}' source-one-line.txt
one
two
three
four
➜ awk 'BEGIN {FS=","; OFS="\n"; ORS="\n------\n"} \
{print $1"\t"$2"\t"$3}' source.txt
101 Ian Bicking Mozilla
------
102 Hakim El Hattab Whim
------
103 Paul Irish Google
------
104 Addy Osmani Google
------
105 Chris Wanstrath Github
------
106 Mattt Thompson Heroku
------
107 Ask Solem Hoel VMware
➜ awk 'BEGIN {FS=","; OFS="\n"; ORS="\n------\n"} \
{print $1,$2,$3}' source.txt | head -12
101
Ian Bicking
Mozilla
------
102
Hakim El Hattab
Whim
------
103
Paul Irish
Google
------
5. NR:记录的数目
➜ awk 'BEGIN {FS=","} {print "Id of record", NR, "is", $1}' source.txt
Id of record 1 is 101
Id of record 2 is 102
Id of record 3 is 103
Id of record 4 is 104
Id of record 5 is 105
Id of record 6 is 106
Id of record 7 is 107
➜ awk 'BEGIN {FS=","} {print "Id of record", NR, "is", $1} END {print "Total number of records is", NR}' source.txt
Id of record 1 is 101
Id of record 2 is 102
Id of record 3 is 103
Id of record 4 is 104
Id of record 5 is 105
Id of record 6 is 106
Id of record 7 is 107
Total number of records is 7
6. FILENAME 和 FNR
FILENAME显示了当前文件, FNR关联到当前文件的记录数。
➜ awk -F, '{print "In file", FILENAME, ": record number", FNR, "is", $1} END {print "Toltal num of records is", NR}' source.txt source-multiple-fs.txt
In file source.txt : record number 1 is 101
In file source.txt : record number 2 is 102
In file source.txt : record number 3 is 103
In file source.txt : record number 4 is 104
In file source.txt : record number 5 is 105
In file source.txt : record number 6 is 106
In file source.txt : record number 7 is 107
In file source-multiple-fs.txt : record number 1 is 101
In file source-multiple-fs.txt : record number 2 is 102
In file source-multiple-fs.txt : record number 3 is 103
In file source-multiple-fs.txt : record number 4 is 104
In file source-multiple-fs.txt : record number 5 is 105
In file source-multiple-fs.txt : record number 6 is 106
In file source-multiple-fs.txt : record number 7 is 107
Toltal num of records is 14
awk变量
变量支持数字,字符和下划线
一个文件source-star.txt内容为:
101,Ian Bicking,Mozilla,1204
102,Hakim El Hattab,Whim,4029
103,Paul Irish,Google,7200
104,Addy Osmani,Google,2201
105,Chris Wanstrath,Github,1002
106,Mattt Thompson,Heroku,890
107,Ask Solem Hoel,VMware,2109
这个文件多加了最后一列star数, 现在统计整个文件的star:
➜ awk -F, 'BEGIN {total=0} {print $2, "got",$4, "star"; total=total + $4} END {print "Total star is "total}' source-star.txt
Ian Bicking got 1204 star
Hakim El Hattab got 4029 star
Paul Irish got 7200 star
Addy Osmani got 2201 star
Chris Wanstrath got 1002 star
Mattt Thompson got 890 star
Ask Solem Hoel got 2109 star
Total star is 18635
➜ echo '1,2,3,4' | awk -F, '{for(i = 1; i <= NF; i++) total = total + i} END {print total}'
10
break continue exit
直接看例子:
# 程序一直运行打印Iteration,并且累加x,直到x等于10停止程序-break
➜ awk 'BEGIN{
x=1;
while(1)
{
print "Iteration";
if ( x==10 )
break;
x++;
}
}'
Iteration
Iteration
Iteration
Iteration
Iteration
Iteration
Iteration
Iteration
Iteration
Iteration
# x从1到10, 如果x等于5 直接直接累加x而不打印
➜ awk 'BEGIN{
x=1;
while(x<=10){
if(x==5){
x++;
continue;
}
print "Value of x",x;x++;
}
}'
Value of x 1
Value of x 2
Value of x 3
Value of x 4
Value of x 6
Value of x 7
Value of x 8
Value of x 9
Value of x 10
# x从1到10,当x等于5的时候程序直接退出
➜ awk 'BEGIN{
x=1;
while(x<=10){
if(x==5){
exit;
}
print "Value of x",x;x++;
}
}'
Value of x 1
Value of x 2
Value of x 3
Value of x 4
关联数组
# awk 的关联数组中item[101]和item["101"]意义一样
➜ awk 'BEGIN { item[101]="Github"; print item["101"]}'
Github
# 可以用in检验是否包含本项
➜ awk 'BEGIN { item[101]="a"; if ( 101 in item ) print "Has 101"}'
Has 101
# 还可以使用for循环读取列表
➜ awk 'BEGIN {
item[101]="Github";
item[21]="Google";
for (x in item)
print item[x]}'
Google
Github
# 多维数组, delete可以删除元素.PS item[2,1]这样的格式有问题
# 因为会被翻译成2#2("2\0342"),假设要设置分隔符可以使用SUBSEP=",";
➜ awk 'BEGIN {item["1,1"]="Github"; item["1,2"]="Google"; \
item["2,1"]="Whim"; delete item["2,1"];
for (x in item)
print "Index",x,"contains",item[x]}'
Index 1,1 contains Github
Index 1,2 contains Google
格式化打印
# \n是换行
Line 1
Line 2
# \t是tab
➜ awk 'BEGIN {printf "Field 1\t\tField 2\tField 3\tField 4\n" }'
Field 1 Field 2 Field 3 Field 4
➜ awk 'BEGIN {printf "Field 1\t\tField 2\t\tField 3\tField 4\n" }'
Field 1 Field 2 Field 3 Field 4
# \v是垂直tab
➜ awk 'BEGIN {printf "Field 1\vField 2\vField 3\vField 4\n"}'
Field 1
Field 2
Field 3
Field 4
# %s字符串; %c单个字符; %d数字; %f浮点数......
➜ cat printf-width.awk
BEGIN {
FS=","
printf "%3s\t%10s\t%10s\t%5s\t%3s\n",
"Num","Description","Type","Price","Qty"
printf "-----------------------------------------------------\n"
}
{
printf "%3d\t%10s\t%10s\t%g\t%d\n", $1,$2,$3,$4,$5
}
➜ awk -f printf-width.awk items.txt
Num Description Type Price Qty
-----------------------------------------------------
101 HD Camcorder Video 210 10
102 Refrigerator Appliance 850 2
103 MP3 Player Audio 270 15
104 Tennis Racket Sports 190 20
105 Laser Printer Office 475 5
内置函数
# int - 将数字转换成整形, 类似的函数还有sqrt, sin, cos...
➜ awk 'BEGIN {print int(4.1);print int(-6.22);print int(strings)}'
4
-6
0
# rand - 随机0-1的数字; srand -初始化随机数的初始值
➜ cat srand.awk
BEGIN {
srand(5);
count=0;
max=30;
while (count < 5) {
# 随机数范围为5-30
rnd = int(rand() * max);
print rnd;
count++;
}
}
# 使用osx的awk随机范围不对
➜ awk -f strand.awk
19
9
21
8
13
# index - 所查字符在字符串中的位置,没找到会返回0
➜ awk 'BEGIN{str="This is a test"; print index(str, "a"); print index(str, "y")}'
9
0
# length - 字符串的长度
➜ awk -F, '{print length($0)}' source.txt
23
24
21
22
26
25
25
# split - 分片 PS:使用awk分片的顺序有问题;
# split第一个参数是要分割的内容,第二个是分割后的结果保存的数组,第三个是使用的分隔符
➜ echo "101 arg1:arg2:arg3" | awk '{split($2,out,":"); for (x in out) print out[x]}'
arg1
arg2
arg3
# substr - 取字符串范围内容;
# 第一个参数是要取的内容, 第二个是开始位置(从1开始),第三个是要取的长度
➜ echo "This is test"|awk '{print substr($3,2,2);}'
es
# sub - 替换原来的字符串,但是只替换第一个符合项; gsub - 替换全部选择项
➜ awk 'BEGIN{str="ThIs is test"; sub("[Ii]s","e", str); print str;}'
The is test
➜ awk 'BEGIN{str="ThIs is test"; gsub("[Ii]s","e", str); print str;}'
The e test
# match - 返回某子字符串是否匹配了某字符串;
# RSTART - awk 自带变量,返回匹配的开始位置
# RLENGTH - awk 自带变量,返回匹配串的长度
➜ awk 'BEGIN{str="This is test"; if (match(str, "test")) {print substr(str,RSTART,RLENGTH)}}'
# tolower/toupper - 把字符串都变成小写/大写
➜ awk 'BEGIN{str="This is test"; print tolower(str); print toupper(str);}'
this is test
THIS IS TEST
# ARGC - 参数的数量; ARGV参数的数组
➜ cat arguments.awk
BEGIN {
print "ARGC=",ARGC
for (i = 0; i < ARGC; i++)
print ARGV[i]
}
➜ awk -f arguments.awk
ARGC= 1
awk
➜ awk -f arguments.awk source.txt
ARGC= 2
awk
source.txt
➜ awk -f arguments.awk source.txt source-star.txt
ARGC= 3
awk
source.txt
source-star.txt
sed 、awk 和 grep 并称 Linux 系统下文本处理三剑客,三者都是非交互式的文本编辑器。
sed 的基本处理单位为记录 (record) ,即文件的行;awk的基本处理单位为域 (field),即文件的逻辑列。
以下内容大部分整理自小明明s Github,有改动。
sed
语法1
格式:
sed [options] {sed-commands} {input-file}
系统里/etc/passwd文件的内容:
例子:
语法2
格式:
sed [options] -f {sed-commands-in-a-file} {input-file}
例子:
语法3
格式:
sed [options] -e {sed-command-1} -e {sed-command-2} {input-file}
例子:
语法4
格式:
例子:
sed 流
利用 sed 流可以实现文件操作:
源文件
source.txt
内容如下:范围
模式匹配
删除行
重定向
替换
格式为:
例子:
替换覆盖
& 代表匹配到的内容
正则
其他
sed 可执行脚本
sed 修改源文件和备份
行后增加和行前插入
语法格式:
sed '[address] a the-line-to-append' input-file
sed '[address] i the-line-to-insert' input-file
例子:
修改行
格式:
sed '[address] c the-line-to-insert' input-file
例子:
其他用法:
awd
示例文件
items.txt
,列分别是id, 描述, 价钱和库存:示例文件
items-sold.txt
, 列分别是id和1-6月的销售情况语法1
例子:
awk数据结构
print
模式匹配
awk内置变量
1. FS:输入字段分隔符
设置分隔符:输入字段分隔符FS
2. OFS:输出字段分隔符
设置输出时的分隔符:输出字段分隔符OFS
3. RS:输入记录分隔符
现在有一个文件 source-one-line.txt 内容为:
想输出
这样的效果。
借用记录分隔符 RS,先把单行内容分割,然后再按 -F 分割输出:
4. ORS:输出记录分隔符
完成一个输出记录后由 ORS 进行分隔(一个输出记录record一般就是一行,在 awk 中打印输出时,{print A, B, C} 相当于 3 个field组成一个record输出)。
直接看例子吧:
5. NR:记录的数目
6. FILENAME 和 FNR
FILENAME显示了当前文件, FNR关联到当前文件的记录数。
awk变量
变量支持数字,字符和下划线
一个文件
source-star.txt
内容为:这个文件多加了最后一列star数, 现在统计整个文件的star:
自增/减
使用++或者--,但是注意符号位置
字符串操作
字符串直接 print 会连接起来, 字符串相加会自动转化成数字相加
复合运算
加减乘除和余数除计算,
文件
assignment.awk
内容如下:比较操作
正则
~ 表示匹配, !~ 表示不匹配
NF (number of fields) 是分割项数目, $NF表示最后一个分割项
if 条件判断
if 条件判断语法为
例子:
if-else语法为:
例子:
while
语法为:
例子,一个文件
while.awk
的内容如下:将文件作为 awk 的输入文件:
do-while
do-while 至少会执行一次,语法格式为:
用 do-while 实现上一次的例子看看会得到什么结果,文件dowhile.awk 内容为:
将文件作为 awk 的输入文件:
(好吧,这个例子我还不是特别懂,姑且先写在这儿)
for
for 循环语法格式:
例子:
break continue exit
直接看例子:
关联数组
格式化打印
内置函数
内置变量
自定义函数
自定义一个函数写入文件
function-debug.awk
:然后调用这个函数:
系统调用
使用
system
函数可以调用shell
命令:awk 高级话题
getline
直接看例子: