Posts 标准输入和参数的管道传输
Post
Cancel

标准输入和参数的管道传输

一个进程通过管道把自己的标准输出流作为标准输入流传输给第二个进程,这是最常用的。但是有时候第二个进程不支持接受标准输入流,只接受普通参数,这就需要对标准输入流做转换。

pipe

假设当前目录下有几个txt文件

1
2
3
4
5
$ find *.txt
chinese.txt
english.txt
maths.txt
name.txt

通过管道传输,find *.txt 的结果成为标准输出流,管道转换后,成为 grep 的标准输入流vvvv。这相当于把find的结果(多行字符串)作为输入流,传输给grep。所以grep对这个输入流(字符串)进行正则查找。

1
2
3
4
$ find *.txt | grep n
chinese.txt
english.txt
name.txt

如果把这个标准输出流,转换成普通参数,就需要通过xargs来明示。

1
2
3
4
5
6
7
$ find *.txt | xargs grep n
name.txt:1 student_name_1
name.txt:2 student_name_2
name.txt:3 student_name_3
name.txt:4 student_name_4
name.txt:5 student_name_5
name.txt:6 student_name_6

这样的执行结果,等价于下面的多文件内容正则查找。结果是从name.txt文本文件的内容中找到含有字符n的内容。

1
$ grep n chinese.txt english.txt maths.txt name.txt

-exec

-exec 目的是执行完第一个进程后接着执行第二个进程,它可以接收第一个进程执行完毕的输出作为普通参数,不能作为标准输入流。而且它只能对输出的结果进行逐行的执行。

比如下面,分号表示-exec执行结束,\是转义。

1
2
3
4
5
6
7
$  find *.txt -exec grep n {} \;
1 student_name_1
2 student_name_2
3 student_name_3
4 student_name_4
5 student_name_5
6 student_name_6

上面的find结果返回4行内容,每一行都是一个文件名。-exec解释后,对这四行逐一执行 grep,所以上述命令相当于执行:

1
2
3
4
grep n chinese.txt 
grep n english.txt 
grep n maths.txt 
grep n name.txt

可见,效率很低。

-ok

-ok 是 -exec的安全版本,每执行一条,都会需要用户交互yes/no (y/n也可以)确认。比如:

1
2
3
4
5
6
7
$ find *.txt -ok ls -al {} \;
< ls ... chinese.txt > ? y
-rw-r--r--. 1 oracle oracle 20 Apr 24 09:13 chinese.txt
< ls ... english.txt > ? n
< ls ... maths.txt > ? n
< ls ... name.txt > ? y
-rw-r--r--. 1 oracle oracle 103 Apr 24 08:29 name.txt

总结

  • 如果第二个命令需要第一个进程的输出流作为输入流来读取,直接使用
  • 如果第二个命令需要第一个进程的输出流作为普通参数来读取,使用xargs 或者 -exec 或者 -ok
  • 如果第二个命令不支持标准输入流而只能接收普通参数,使用xargs 或者 -exec 或者 -ok
This post is licensed under CC BY 4.0 by the author.

grep或sed快速定位大日志文件

权限转换的Shell脚本