grep-sed-awk
总而言之
grep、sed 与 awk 是 linux 各大发行版中经常预置的三种文本处理工具。因其常见,往往被业内称为 linux 的“三剑客”。它们的共同点在于他们都是命令式而非交互式的,这与我们常用的 vim 或 nano 不同,同时也加大了学习成本;但也正因如此,它们都很适合嵌入到脚本之中,自动化完成文本处理任务。
关于 grep
grep 可以搜索文本文件中包含关键字的行,其配合正则表达式可以实现更强大的功能。一般来说,grep 命令是这样构成的:
1 | grep "[关键字]" [文件路径] |
特别的,我们也时常将其他命令的输出结果重定向给 grep 命令,再进行筛选。类似这样:
1 | [命令] | grep "[关键字]" |
而 grep 的所谓“关键字”是支持正则表达式的,使用“-E”参数能获得更强的正则表达式支持。grep 命令的常见参数如下:
| 参数 | 全称 | 备注 |
|---|---|---|
| -E | –extended-regexp | 使用扩展的正则表达式规则 |
| -f | –file=[文件] | 从文件中读取要使用的正则表达式 |
| -i | –ignore-case | 忽略大小写 |
| -w | –word-regexp | 仅匹配的(被空格包裹的)词 |
| -x | –line-regexp | 仅匹配的行 |
| -v | –invert-match | 反选 |
| -n | –line-number | 显示行号 |
| -C | –context=[数字] | 打印指定行数的上下文 |
案例
搜索 长恨歌.md 中含“马嵬坡”的行及其上下文:
1 | grep -C 2 "马嵬坡" ChanghenGe.md |
输出:
峨嵋山下少人行,旌旗无光日色薄。蜀江水碧蜀山青,圣主朝朝暮暮情。
行宫见月伤心色,夜雨闻铃肠断声。天旋地转回龙驭,到此踌躇不能去。
马嵬坡下泥土中,不见玉颜空死处。君臣相顾尽沾衣,东望都门信马归。
归来池苑皆依旧,太液芙蓉未央柳。芙蓉如面柳如眉,对此如何不泪垂。
春风桃李花开日,秋雨梧桐叶落时。西宫南内多秋草,落叶满阶红不扫。
搜索根目录中含 bin 的文件:
1 | ls -lhrt / | grep "bin" |
输出:
lrwxrwxrwx 1 root root 7 5月 2 2023 bin -> usr/bin
lrwxrwxrwx 1 root root 8 5月 2 2023 sbin -> usr/sbin
搜索 长恨歌.md 中含数字的行:
1 | grep -E "[一二三四五六七八九十百千万]" ChangHenGe.md |
输出:
天生丽质难自弃,一朝选在君王侧。回眸一笑百媚生,六宫粉黛无颜色。
承欢侍宴无闲暇,春从春游夜专夜。后宫佳丽三千人,三千宠爱在一身。
九重城阙烟尘生,千乘万骑西南行。翠华摇摇行复止,西出都门百余里。
六军不发无奈何,宛转蛾眉马前死。花钿委地无人收,翠翘金雀玉搔头。
楼阁玲珑五云起,其中绰约多仙子。中有一人字太真,雪肤花貌参差是。
金阙西厢叩玉扃,转教小玉报双成。闻道汉家天子使,九华帐里梦魂惊。
风吹仙袂飘飖举,犹似霓裳羽衣舞。玉容寂寞泪阑干,梨花一枝春带雨。
含情凝睇谢君王,一别音容两渺茫。昭阳殿里恩爱绝,蓬莱宫中日月长。
钗留一股合一扇,钗擘黄金合分钿。但教心似金钿坚,天上人间会相见。
临别殷勤重寄词,词中有誓两心知。七月七日长生殿,夜半无人私语时。
关于 sed
sed 可以通过一句简单的脚本来处理文本文件,一般来说 sed 命令是这样构成的:
1 | sed [参数] [脚本] [文件] |
不加 -i 参数的话,命令会将处理后的文件输出到屏幕上,而不会改动原始文件。
脚本大致是由“[行号][动作][新内容]”组成的,其中省略行号将使[动作]全局生效。比如 sed -e '1i\ABCD' test.txt 表示在 test.txt 的首行之前插一句“ABCD”。
sed命令中的参数与动作的说明如下:
| 参数 | 说明 | 动作 | 说明 |
|---|---|---|---|
| -e | expression,指定要执行的脚本 | i | insert,在指定的行之前插入内容 |
| -f | file,指定要执行的脚本文件 | a | append,在指定的行之后插入内容 |
| -n | silent,仅显示经过处理的行 | d | delete,删除指定行 |
| -i | in-placd,将处理后的文件覆盖到原始文件上 | c | copy,取代指定行 |
| s | substitute,局部替换内容 | ||
| p | print,打印指定行,通常和-n连用 |
案例
输出 长恨歌.md 的前四行
1 | sed -n -e '1,4p' ChangHenGe.md |
输出:
### 长恨歌
> 【唐代】白居易
汉皇重色思倾国,御宇多年求不得。杨家有女初长成,养在深闺人未识。
天生丽质难自弃,一朝选在君王侧。回眸一笑百媚生,六宫粉黛无颜色。
将 长恨歌.md 中的所有的“一”替换成“壹”
1 | sed -e 's/一/壹/g' ChangHenGe.md |
输出略。
关于 awk
awk是一款用以格式化处理文本文件的编辑器,它也是通过一些简单的脚本处理文本文件的。所不同的是,它将每行文本(或记录,record)按指定分割符分割(默认是空格),并将其赋给一系列变量(或字段,field),比如$1代表这条记录的第一个字段,$2代表第二个;依次类推;特别的,$0代表所有的字段,$NF代表最后一个字段,$NF-1代表倒数第二个字段。
和sed类似,一般来说awk命令是这样构成的:
1 | awk [参数] [脚本] [文件] |
案例
以“,”和“。”为分割符,每行逐句输出 长恨歌.md
1 | awk -F '[,。]' '{for(i=1; i<NF; i++) print $i}' ChangHenGe.md |
以“,”和“。”为分割符,输出 长恨歌.md ,但为每个字段间隔开更大的距离
1 | awk -F '[,。]' '{printf "%-10s %-10s %-10s %-10s\n", $1, $2, $3, $4}' ChangHenGe.md |
测试用例
1 | ### 长恨歌 |
