Motivation

最近在做操作系统的实验,经常用到 grep 命令和管道,之前也经常用到这样的命令:

ps aux | grep nginx

但是对于很多 grep 和管道的用法还不是很熟悉,所以干脆就单独拿出来学习一下。

grep

维基百科给出了 grep 命令的介绍:

在给出文件列表或标准输入后,grep会对匹配一个或多个正则表达式的文本进行搜索,并只输出匹配(或者不匹配)的行或文本。

grep  的全称是 global regular expression print ,所以其实 grep 命令就是 linux 下的一个强大的使用正则的文本搜索命令。

比如上面用到的例子 ps aux | grep nginx 就是查看当前进程中包含 nginx 的进程。

grep 当然还有很多的参数,这里不赘述了,大概列举几个比较常用的使用:

文件中关键词进行搜索

比如操作系统实验中,需要在整个项目中搜索用到了 argint 函数的文件,如果使用像 vscode 这样高级的图形化界面编辑器,直接使用全局搜索即可,但是在枯燥的命令行中,就需要用到 grep 命令了:

alpha@VM-199-186-ubuntu:~/proj0-base$ grep argint *
defs.h:int             argint(int, int*);
syscall.c:argint(int n, int *ip)
syscall.c:  if(argint(n, &i) < 0)
syscall.c:  if(argint(n, &addr) < 0)
sysfile.c:  if(argint(n, &fd) < 0)
sysfile.c:  if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0)
sysfile.c:  if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0)
sysfile.c:  if(argstr(0, &path) < 0 || argint(1, &omode) < 0)
sysfile.c:     argint(1, &major) < 0 ||
sysfile.c:     argint(2, &minor) < 0 ||
sysfile.c:  if(argstr(0, &path) < 0 || argint(1, (int*)&uargv) < 0){
sysproc.c:  if(argint(0, &pid) < 0)
sysproc.c:  if(argint(0, &n) < 0)
sysproc.c:  if(argint(0, &n) < 0)

更高级的搜索

grep 不单单支持普通的字符串搜索,毕竟它是使用正则表达式,所以这里我们也可以使用正则表达式来进行跟高级的搜索。

比如这里我们依然使用上面这样的场景,我们搜索以 arg 开头 int 结尾的字符串:

grep 'arg.*int' *

管道

说完 grep 命令,我们再来说说管道,管道命令的操作符就是上面用到的 |

直白的说,管道的作用就是将 | 前的一个命令的输出作为 | 后的命令的输入。

所以 ps aux | grep nginx 就是将 ps aux 的输出内容作为 grep nginx 的输入进行查询。

有两个注意点就是:

  • 管道命令只处理一个命令的正确输出,不处理错误输出
  • 管道的后一个命令必须能接受标准输入

重定向

讲到管道,顺便讲讲数据重定向

文件描述符

在讲重定向之前,先说说文件描述符吧。一般执行一条命令,首先会从键盘或者文件中获得一个输入,命令执行完成后,把输出结果输出到屏幕(standard output / standard error 默认都是屏幕)。

linux shell 中常用的输入输出操作符有:

  • 标准输入(stdin):代码为 0,使用 < 或 <<
  • 标准输出(stdout):代码为 1,使用 > 或 >>
  • 标准错误输出(stderr):代码为 2,使用 2> 或 2>>

使用上面这些文件描述符就可以做到数据重定向了

输出重定向

举个栗子,ls test.sh test1.sh 命令是判断当前目录是否存在 test.shtest1.sh 两个文件。

ls: test1.sh: 没有这个文件和目录
test.sh

ls: test1.sh: 没有这个文件和目录 这是一条错误输出,而 test.sh 是一条正确输出,那么我们希望把错误输出写到 err.txt 和正确输出写到 result.txt 中,那我们就可以使用到上面提到的输出操作符进行重定向:

ls test.sh test1.sh 1>result.txt 2>err.txt

输入重定向

比如 cat 命令后面跟的参数默认都是键盘输入,如果我们希望使用文件输入,那就需要输入重定向。

cat < catfile

小结

在写一些 shell 脚本的这些命令还是挺有用的。