coolshell是个很不错的小站,请大家多关注
awk
awk [options] 'script' files
下面我们详细描述script区域
关键字
{} 代表对每一行进行处理的语句
BEGIN{} 代表对每一行进行处理前执行的语句
END{} 代表对每一行进行处理后执行的语句
$ cat score.txt
Marry 2143 78 84 77
Jack 2321 66 78 45
Tom 2122 48 77 71
Mike 2537 87 97 95
Bob 2415 40 57 62
cat cal.awk
#!/bin/awk -f
#运行前
BEGIN {
math = 0
english = 0
computer = 0
printf "NAME NO. MATH ENGLISH COMPUTER TOTAL\n"
printf "---------------------------------------------\n"
}
#运行中
{
math+=$3
english+=$4
computer+=$5
printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5
}
#运行后
END {
printf "---------------------------------------------\n"
printf " TOTAL:%10d %8d %8d \n", math, english, computer
printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR
}
awk -f cal.awk score.txt
语句
1.打印 '{print $1,$2 ...}'
打印文件中每一行的第一列和第二列;其中$1代表第一列,$2代表第二列,以此类推,$0代表每一列,即一整行
2.格式化输出 'printf "%-20s %-20s %s\n",$4,$5,$6 '
3.过滤 '$3==0 && $6=="LISTEN" '
awk支持比较运算符 == != > < >= <=; 字符串可以使用 “ ”
第二种过滤是 字符串匹配 ~ / pattern / pattern匹配时可以 使用 | ,取反 ' !/pattern/ '
'$6 ~ /WAIT/ || NR==1 {print NR,$4,$5,$6}'
当然也可以 在外面匹配 awk '/LISTEN/ ' filename
4.拆分文件 awk 'NR!=1{print > $6} '
NR!=1表示排除第一行,然后把第六列相同的值保存到命名为该值的文件中
复杂些加上条件语句
'NR!=1{
if($6 ~ /TIME|ESTABLISHED/) print > "1.txt";
else if($6 ~ /LISTEN/) print > "2.txt";
else print > "3.txt" }'
5.内置变量
$0 | 当前记录(这个变量中存放着整个行的内容) |
$1~$n | 当前记录的第n个字段,字段间由FS分隔 |
FS | 输入字段分隔符 默认是空格或Tab |
NF | 当前记录中的字段个数,就是有多少列 |
NR | 已经读出的记录数,就是行号,从1开始,如果有多个文件话,这个值也是不断累加中。 |
FNR | 当前记录数,与NR不同的是,这个值会是各个文件自己的行号 |
RS | 输入的记录分隔符, 默认为换行符 |
OFS | 输出字段分隔符, 默认也是空格 |
ORS | 输出的记录分隔符,默认为换行符 |
FILENAME | 当前输入文件的名字 |
awk 'BEGIN{FS=":"} {print $1,$3,$6}' /etc/passwd 使用:作为分隔符,而不是space
也可以awk -F: '{print $1,$3,$6}' OFS="\t" /etc/passwd,其中想要制定多个分隔符 可以使用-F ' [;:] '
(2).NR & FNR 分隔符
如果使用过滤条件,有想要打印出第一行的所有内容,可以使用NR==1;FNR表示自己的行号
awk '$3==0 && $6=="ESTABLISHED" || NR==1 {printf "%02s %s %-20s %-20s %s\n",NR, FNR, $4,$5,$6}' netstat.txt
awk编程
1.变量赋值
2.计算运算符 + - * / 甚至还支持 += ++ 等
3.条件语句,循环语句
statement1;
} else if (expression1) {
statement2;
} else {
statement3;
}
8.length
9.使用环境变量
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
sed
玩sed需要熟练操作正则表达式
sed的很多操作方式非常类似于vim
sed [options] "commands" filename
老规矩,先看commands
命令
替换
和vim一样
sed “s/source/dest/g" filename
如果想要使用单引号,最好外包双引号,而且使用双引号可以哦那个过\ 转意其他字符‘
1)简单正则表达式
^开头 ^s 匹配以s开头
$结尾 s$匹配以s结尾
\< 词头 \<s 以s开头的词
\> 词尾 \>s 以s结尾的词
. 表示任何单个字符
* 表示某个字符出现了0次或多次 ? 表示某个字符出现了1次或多次
[] 字符集合 [abc] 表示匹配 a 或者 b 或者 c ;如果 [^a] 表示a取反,除了a之外的字符
可以是用正则表达式来做字符替换,下面介绍写例子
2) 替换的文本写回到源文件
两种办法 1.使用管道 sed “commands" filename > filename
2.使用options -i sed "commands" filename 即可
3)在每行开头加入 #
sed "s/^/#/g" filename
4) 去掉html的tags
sed 's/ < [^>] * > / / g " filename
5)替换特定行和特定列
sed "3,$ s/source/dest/g" filename 替换第三行到最后一行所有
sed "3,$ s/source/dest/1" filename 只替换第二个符合source的字段
sed "1,3 s/source/dest/3g" filename 替换第一行到第三行的每一行中第三个到最后一个符合source的字段
6)多个匹配
两种办法。1.在commands中使用分号; sed " s/source1/dest1/g ; s/source2/dest2/g " filename
2.使用options -e sed -e "s/source1/dest1/g" -e "s/source2/dest2/g" filename
7)&符号
可以使用&值代前面的pattern
sed "s/pattern/[&]/g" filename 这样就在所有patter左右加了[]
8)圆括号匹配
匹配出来的pattern的第一个用 \1 指代,以此类推
sed “s/ pattern1, pattern2 / \1:\2/g " filename
其他命令
分为n命令,c,p,a&i,d命令等
1)N命令,把下一行的内容纳入缓冲区当作匹配
sed 'N;s/\n/,/' pets.txt 将两行合并为一行,并且中间使用,分割
2)插入 a & i
sed "$ a test " filename 后面插入
sed "$ i test " filename 前面插入
也可以使用匹配
sed "/my/a ----" my.txt
3)替换c命令
sed "2 c test" my.txt
sed "/fish/ c test" my.txt
4) 删除d命令
同理,,,
5)打印p命令
高阶sed待续,哈哈
http://sebug.net/paper/books/awk/