sed,awk与grep

xeonds

2023-07-10 16:17:33

前言

关于标题:实际上,sed,awk和grep有一个共同的爹叫ed。sed和awk的区别是控制指令不太一样,而grep是起源于ed的一个指令:g/re/p,即全局-正则表达式匹配-打印,相当于把这个ed指令提取出来专门用于编辑。

之前学了Vim,不过Vim不太容易和其他命令行工具结合实现一些自动化任务。随后我将目光投向了sed和awk,它们二者都满足这个条件:可以将一个源的数据经过一些预定义的变换,输出到另一个源中。这其中,我对sed相对更加熟悉一些,awk我感觉可能更复杂一些,而sed只需要正则表达式就行。比如我之前接触到的第一个sed表达式:

sed -i 's@^\(deb.*stable main\)$@#\1\ndeb https://mirrors.tuna.tsinghua.edu.cn/termux/apt/termux-main stable main@' $PREFIX/etc/apt/sources.list

上面那段是termux清华源的换源指令。单就命令格式上来看,我觉得和Vim的%s替换表达式比较接近。

没接触之前,一直觉得这玩意很神奇;接触后更感觉这东西的设计太棒了,只需要指令,就能完成大段内容的编辑。

后来接触了正则和Vim之后觉得似曾相识,才发现sed的用法很像Vim的替换指令+正则。而且这一套下来,效率提升真不小。以前做一些爬虫都编辑麻烦,现在直接写个脚本就完事了。比如,我最近为了尝试这三个流编辑器,写了一个爬新闻的脚本:

#!/bin/bash

echo -e "# IT news Today\n\n$(wget -qO- https://www.ithome.com/block/rank.html | grep -oP '<li>\s*<a\K[^>]+' | awk -F '"' '{print "["$2"]("$6")"}' | sed 's/^/- /g')"

这是一个简单的单行脚本:借助管道,将wget抓取到的网页直接交由grep,让它使用Perl正则表达式将新闻标题和链接匹配出来,再交由awk将具体的字段分离出来并按照markdown的标准进行加工,最后交由sed使用行编辑模式在每一行前面加上一个-变换为markdown的列表。最后,将输出返回给echo -e,得到加上标题的、完整的输出。

其实,上面的例子只用grep+sed/awk就行,但是为了表现三个编辑器各自的特点,还是安排它们共同完成了这个变换工作。希望这个例子能给你带来一个粗浅的印象。

那么,现在就开始正篇吧。

sed

首先说说sed它爹ed,这玩意是个很经典的行编辑器。不光可以交互编辑(类似于Vim,不过只能通过交互式指令输出操作结果,比如p输出当前行内容之类的),而且还能把操作指令存储下来

基本介绍

sed是一个流编辑器,它可以对文本文件或标准输入进行处理和编辑。sed的基本用法是:

sed [options] 'script' file

其中,options是一些可选的参数,script是一些sed命令,file是要处理的文本文件。下面是一些常用的options:

sed的script由一些地址和命令组成,地址可以指定要处理的行,命令可以指定要执行的操作。下面是一些常用的地址和命令:

示例:

sed -n '1,3p' file.txt
sed '1,3d' file.txt
sed 's/^/#/g' file.txt
sed 's/.*/\U&/g' file.txt

参考资料

¹: Linux sed 命令 | 菜鸟教程 ²: sed 命令快速入门 - 知乎 ³: sed完全教程 - 知乎

awk

grep