首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用sed编辑文件描述符

如何使用sed编辑文件描述符
EN

Stack Overflow用户
提问于 2016-02-01 16:45:25
回答 2查看 1.2K关注 0票数 1

我成功地使用了带sed的文件描述符,并在标准输出上给出了结果。提供一个文件"file.txt“,其中包含:

代码语言:javascript
复制
$ cat file.txt
foo
Foo

我打开一个文件描述符到file.txt,打开一个子shell,并将这个文件描述符给sed:

代码语言:javascript
复制
$ (sed "/Foo/c\\bar" <&9 ) 9< file.txt
foo
bar

结果是正确的。

现在,如果我想使用sed的-i选项来改变位置,我就有麻烦了。我在读写模式下打开文件描述符,然后将它作为输入文件提供给sed:

代码语言:javascript
复制
$ (sed -i "/Foo/c\\bar" <&9 ) 9<> file.txt
sed: no input file

我不明白为什么缺少一个输入文件。在使用-i选项时,sed可能需要文件名,而不是文件描述符?

我尝试了一种解决办法,当然不像预期的那样起作用:

代码语言:javascript
复制
$ (sed "/Foo/c\\bar" <&9 >&9 ) 9<> file.txt
$ cat file.txt
foo
Foo
foo
bar

虽然我希望:

代码语言:javascript
复制
$ cat file.txt
foo
bar

提前感谢您的帮助!杜纳托托斯

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-02-01 17:05:01

sed -i需要一个文件名。您不能传递/dev/stdin (或类似的),因为sed将尝试在/dev中创建一个临时文件。

您甚至不能将sed的输出保存到临时文件中,然后再次在文件描述符中写入输出,因为您不能在Bash中倒带文件描述符。

您可以做的是从文件描述符中计算出原始文件名。您可以通过使用链接/proc/self/fd/9来做到这一点,如下所示:

代码语言:javascript
复制
sed -i "/Foo/c\\bar" "$(readlink /proc/self/fd/9)"

但是,请注意,原始文件可能已被删除或重命名,在这种情况下,此解决方案将无法工作。而且,这个解决方案期望/proc是可用的,但情况可能并不总是这样。/dev/fd/9可能是一个很好的替代品。

需要注意的另一件事是,sed -i的工作方式是用一个新的文件替换该文件:在运行sed -i之后,fd 9不会引用新创建的文件。要解决这个问题:

代码语言:javascript
复制
name="$(readlink /proc/self/fd/9)"
cp "$name" "$name.tmp"
sed "/Foo/c\\bar" "$name.tmp" > "$name"

这样,fd 9在运行sed之前和之后仍然引用相同的文件。您可能希望使用mktemp创建临时文件,使用atexit确保删除该文件。

票数 2
EN

Stack Overflow用户

发布于 2016-02-01 17:29:58

您不能用sed编辑任何“就位”的内容,这是-i命名错误的一个很好的例子。gnu通过创建一个新文件、将输出写入它,然后重命名该文件来实现-i。如果不给sed原始文件名,它就不知道如何重命名它。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35135764

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档