如何沿管道动态地更改文件?
我可能正在寻找一种在管道开头缓冲文件的方法,这与此形成对比:
cat foo.txt | grep bar > foo.txt
... 将保护输入数据不被管道本身破坏。有这样的缓冲区吗?
答案1
我猜 sed 仍然可能会创建临时文件,但是下面的操作可能会实现你想要的效果?(对此使用 strace 可能会显示 sed 是否创建了临时文件)。
sed -i '/bar/!d' foo.txt
感叹号反转匹配,d 代表删除,因此这将删除所有不包含 bar 的行。
答案2
答案3
使用>>来保存内容。
cat foo.txt | grep bar >> foo.txt
现在将其附加到文件。
据我所知,在 shell 中没有直接的方法将数据添加到文件前面。如果要添加,可能需要在中间使用临时文件。
答案4
最好的办法是记住文件在 unix 中的工作方式——只要有指向该文件的链接(打开文件的目录或进程),该文件就存在。
因此,打开文件,删除该目录条目,然后运行写入具有相同名称但链接到不同 inode 的新目录条目的进程。
最后,这个的优点在于它适用于任何类型的管道操作,而不仅仅是可以执行临时文件缓冲区破解的操作。
{ rm file ; sed -e s/this/that/g > file ; } < file
警告——如果您必须将重写作为原子操作,这可能会导致灾难。unix 不提供锁定文件的干净方法,尤其是在 shell 级别。如果您在运行 NIS 之类的繁忙系统上执行诸如编辑密码文件之类的操作,那么在黑暗时代这是一个问题。任何时候,如果有多个进程正在读取/写入文件,如果您的系统繁忙或重要,请务必小心。
唯一 100% 确定是原子的操作是目录条目操作 - rm / ln / mv(在同一文件系统上)。
所以现在事情变得更长、更丑陋了……
其中的数学部分需要 posix shell 或类似扩展的 bourne shell
c=0
while
f=$SECONDS
test -f file.$c.tmp
do
c=$(($c+1))
done
grep stuff < file > file.$c.tmp && mv file.$c.tmp file