第四章 过滤程序
grep/egrep/fgrep
fgrep 可同时搜索多个文字字符串
egrep 解释真正的正则表达式
-f fgrep/egrep可通过该选项从指定的文件中读取模式
------------------------------------------
grep/egrep正则表达式
c 任何与自己匹配的非特殊字符
/c 去掉字符c的任何特殊意义
^ 行首
$ 行尾
. 任意单个字符
[...] 匹配...中的任一字符
[^...] 匹配未在...中出现的字符
/n 与第n个/(.../)匹配的字符(仅grep可用)
r* 匹配r零次或多次
r+ 匹配r一次或多次(仅egrep)
r? 匹配r一次或零次(仅egrep)
xy y紧随x
x|y x或y(仅egrep)
/(r/) 带括号的正则表达式r(仅grep),可嵌套
(r) 正则表达式r(仅egrep),可嵌套
在BSD下,(r)不能直接使用,而"(c)"可用,意思同c,
而'(c)'的意思是匹配3个字符,包括两边的括号
==========================================
sort
+n 按第n列排序,第一列n=0
-f 按字母表顺序排序,不区分大小写
-u 删除重复行
==========================================
comm
显示结果的说明:
第一列: 第一个文件不同于第二个文件部分
第二列: 第二个文件不同于第一个文件部分
第三列: 两个文件相同的部分
-1 禁止显示第一列
-2 禁止显示第二列
-3 禁止显示第三列
上面三条可合并
$$$$$$$$$$$$$$$$$$$$$$$$$$$$
无法解释的问题:
文件f1的内容:
abcd
efgh
ijkl
文件f2的内容:
abcd
kefgh
ijkl
但是结果竟然是这样:
$ comm f1 f2
abcd
efgh
ijkl
kefgh
ijkl
我认为结果不该像上面,而应该是这个:
$ comm f1 f2
abcd
efgh
kefgh
ijkl
可是假如f2的内容是:
abcd
efghk
ijkl
结果如我所想,显示如下:
$ comm f1 f2
abcd
efgh
efghk
ijkl
==========================================
tr 转换字符
示例:
tr a-z A-Z 将输入中的所有小写转换为大写
==========================================
sed stream editor
a / 将行添加到输出直至不以/终结的行
b 标号 转至命令 :标号
c / 对随后的文本,如同a命令那样逐行修改
d 删除行,读下一个输入行
i / 在下一个输出前插入下面的文本
l 按行列表,使所有的非打印字符可见
p 打印行
q 退出
r 文件 读文件,拷贝内容到输出
s/RegExp/str/f 用str替换RegExp,若f=g,置换所有变化;f=p,打印;f=w,写入文件
t 标号 测试,若对当前行作了替换,转至标号
w 文件 将行写到文件
y/str1/str2/ 用str2中的对应字符替换str1中的每个字符(不支持范围值)
= 打印当前输入行号
! 命令 仅当行未被选取时,执行sed命令
: 标号 为b和t设置标号
{} 将{}之间的命令视为一组
SED单行脚本快速参考
http://sed.sourceforge.net/sed1line.txt
http://sed.sourceforge.net/sed1line_zh-CN.html
-n 关闭自动打印
sed -n '/模式/p' 这样只有匹配模式的行才被打印
n 把下一行的内容写到模式中,具体参见示例:
sed 'n;d' 删除偶数行
sed 'n;p'
sed 'p;n'
sed 'p;n;n'
sed -n 'n;p'
sed -n 'p;n'
sed -n 'p;n;n'
关于Tab的输入:
如果是在命令行输入,可以按crtl+v再按crtl+i
如果是写成脚本执行,直接按TAB
多命令示例:
sed 's/^/ /
3q'
作用:每行的行首加上Tab
打印前3行后退出
注意:每条命令应放在单独的行,sed会忽略每行行首的空格和Tab
-f 命令文件 从命令文件中获取命令
示例:
fsed 写有sed命令的文件
命令文件内容中只能有命令部分,即命令行下引号中的内容
file 要处理的文件
sed -f fsed file
实例:
$sed 's/$//
> /' #插入新行,注意上一行最后的反斜线
$sed 's/[ <Ctrl+v,Ctrl+i>][ <Ctrl+v,Ctrl+i>]*//
> /g' #用换行替换每行的空格或Tab,这样就可以变成每行一个单词
sed -n '20,30p' 打印20-30行
sed '1,10d' 删除1-10行
sed '1,/^$/d' 删除直至包括第一个空行
sed -n '/^$/,/^end/p' 打印从一个空行开始到end结束的行组
sed '$d' 删除最后一行
shell脚本
ls -t |sed '/^'$1'$/q' 打印目录中比指定目录更新的文件
ls -tr|sed '/^'$1'$/q' 打印目录中比指定目录更旧的文件
==========================================
模式扫描与处理语言awk
$ awk '程序' 文件名
程序:
模式 {action}
...
模式 {action}
awk -f 命令文件 文件名
awk自动将输入行分段(空格、Tab)
这些字段可引用为$1,$2,...,$NF
NF为字段个数,本身也是一个变量
-F fs 指定fs作为分隔符
awk -F 分隔符 {action}
比较示例:
$2 == "" 第二个字段为空
$2 ~ /^$/ 第二个字段与空串匹配
$2 !~ /./ 第二个字段不与任何字符相匹配
length($2) == 0 第二个字段的长度为零
两个特殊模式:
BEGIN {action} 在读入第一个输入行前执行
END {action} 在处理完最后一行后执行
awk中的变量:
不用声明、变量缺省值为零
内部变量:
FILENAME 当前输入的文件名
FS 字段分隔字符
NF 输入记录中的字段个数
NR 输入记录数
OFMT 数字的输出格式(缺省为%g)
OFS 输出字段分隔符(缺省为空格)
ORS 输出记录分隔符(缺省为换行)
RS 输入记录分隔符(缺省为换行)
awk控制流:
可以使用if、for、while
可以使用关联数组
awk内嵌函数:
cos(表达式) 余弦
exp(表达式) 取自然指数
getline() 读入下一行,若文件结束,返回0,否则返回1
index(str1,str2) str1中str2的位置,若不存在,返回0
int(表达式) 取整,向0截取
length(str) 长度
log(表达式) 自然对数
sin(表达式) 正弦
split(str,a,c) 以c为分隔符将str分割成a[1]...a[n]并返回n
sprintf(格式,...) 格式化...
substr(str,m,n) 截取str中索引m开始的n个字符的子串