LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
12
返回列表 发新帖
楼主: syisyi

请教用sed删除替换文件中某行的语句的重定向

[复制链接]
发表于 2010-10-17 02:40:28 | 显示全部楼层
我认为这个过程没有什么优先级的。是随机竞争的结果,跟文件大小什么的都还有关系。
运行管道前后程序,清空文件以供输入的过程虽然有先后,但是几乎是同步进行的。

bash运行第一个程序,之后运行第二个程序(这个时候第一个程序未必启动结束)接收第一个程序的输出,之后清除文件用于接收第二个程序的输出。
这几个程序的启动过程在cpu里就存在竞争,本身就未必是第一个程序启动比第二个程序快,可能在第一个程序启动结束之前,系统就已经把文件清空了(这种情况输出为空),也可以在第一个程序启动结束之后(开始读入文件),系统才把文件清空(这种情况输出不为空,但如果文件很大最后输出的文件可能是不完整的)。

可以做如下测试:
1.
ps |cat |sed -n 'p' >a
可以看到三个程序,ps、cat、sed的进程号是增加的,也就是说,它们是顺序启动的。
2.
建一个文件:
#!/bin/sh
sed -n 'p' a|sed -n 'p' |..............|sed -n 'p' >a
a先用小文件,只用一次管道的话,a被清空的可能性很大,但是如果有十几重甚至几十重管道的话a就很可能不为空。
在a不被清空的情况下,把a换成一个大文件再执行,会发现a的内容不完整。
这说明sed不是一次把文件的内容全部读入的,它第一次读的时候还能读到内容,但当它想再读一些的时候文件被清掉了,所以写回文件a的内容也就不完整了。
回复 支持 反对

使用道具 举报

发表于 2010-10-21 10:31:43 | 显示全部楼层

  1. [jacuro@lab1 ~]$ cat t.txt
  2. this is the first line
  3. this is the second line
  4. this is the third line
  5. [jacuro@lab1 ~]$ cat t.sh
  6. #!/bin/bash
  7. sed '/first/d' t.txt | sed '/second/d' > t.txt
  8. [jacuro@lab1 ~]$ ./t.sh
  9. [jacuro@lab1 ~]$ cat t.txt
  10. [jacuro@lab1 ~]$
复制代码

不管是直接在命令行执行,还是在script里面执行,我得到结果,总是空文件,我认为这才是合理的结果。
Bash manual里面提到:

3.6 Redirections
Before a command is executed, its input and output may be redirected using a special notation interpreted by the shell

如下测试:

  1. [jacuro@lab1 ~]$ ( sleep 60; touch t2.txt ) > t1.txt
  2. [jacuro@lab1 ~]$ ls -l t1.txt t2.txt
  3. -rw-rw-r-- 1 jacuro jacuro 0 Oct 21 10:25 t1.txt
  4. -rw-rw-r-- 1 jacuro jacuro 0 Oct 21 10:26 t2.txt
  5. [jacuro@lab1 ~]$
复制代码

t1和t2时间相差一分钟,可以知道,重定向是在命令执行前发生。

其实此问题在 http://www.linuxsir.cn/bbs/thread372492.html 中已经讨论过。
回复 支持 反对

使用道具 举报

发表于 2010-10-24 17:20:00 | 显示全部楼层
Post by rabaey;477857

你的问题斑竹已经给你指出来了阿,加一个管道后
sed "command" file.name | sed "command" > file.name
第二个sed的输入是管道,不会晴空那个文件的。

如果不加
sed "command" file.name > file.name
文件file.name就会被事先晴空,然后再送给sed命令。
你这个解释行不通的。
请看。
$ cat file | > file
# 上面来做的话,file文件依然会清空
# 也许是和sed的特性有关系的,sed是流编辑器 ,它只显示改变后的状态,读取一行源文件,把源文件输入缓存,之后
# 编辑缓存,输出并不改变原文件
回复 支持 反对

使用道具 举报

发表于 2010-10-25 10:46:10 | 显示全部楼层
jacuro正解,shell在管道行中的任何命令执行前,已经把重定向操作符处理完毕,因此在重定向操作符是“>”时且noclobber选项没开时,文件内容被毁,管道行中的任何命令看到的该文件都是空的。
另外,至于管道行中的命令分配std{in,out}和处理重定向的先后顺序,POSIX:2008的XCU中说:
The standard input, standard output, or both of a command shall be considered to be assigned by the pipeline before any redirection specified by redirection operators that are part of the command.
因为fork和exec是分离的,因此这里并不是说是在命令执行之后才处理重定向的...吗?吧!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表