3

该文件最初是

$cat so/app.yaml 
application: SO
...

我运行以下命令。我得到一个空文件。

$sed s/SO/so/ so/app.yaml > so/app.yaml 
$cat so/app.yaml 
$

如何使用 SED 编辑文件而不给我一个空文件?

4

4 回答 4

16
$ sed -i -e's/SO/so/' so/app.yaml

-i手段到位。

于 2009-04-06T18:59:54.350 回答
5

管道中使用的>将在管道全部设置好时打开输出文件,即在命令执行之前。因此,输入文件在执行之前被截断sed。这是所有 shell 重定向的问题,而不仅仅是sed.

Sheldon Young 的回答展示了如何使用就地编辑。

于 2009-04-06T19:07:30.293 回答
5

您为这项工作使用了错误的工具。sed是一个编辑器(这就是它被称为sed的原因),所以它用于对管道中的流进行动态编辑。edOTOH 是一个文件编辑器,它可以做所有sed可以做的事情,除了它适用于文件而不是流。(实际上,它是相反的:ed是原始实用程序,并且sed是避免为流创建临时文件的克隆。)

ed工作方式非常相似sed(因为sed只是一个克隆),但有一个重要区别:您可以在文件中移动,但不能在流中移动。因此,所有命令都ed带有一个地址参数,该参数告诉在文件中ed何处应用命令。在您的情况下,您希望在文件中的任何位置应用命令因此 address 参数只是,因为a,b表示“从行a到行b”,默认为a( 1beginning-of-file),默认为b( $end-of -file),因此将它们都排除在外意味着“从文件开头到文件结尾”。然后是s(替代品),其余的看起来很像sed

因此,您的sed命令s/SO/so/变成了 ed 命令,s/SO/so/

而且,由于ed是文件编辑器,更准确地说,是交互式文件编辑器,我们还需要编写 ( w) 文件并退出 ( q) 编辑器。

这是它的整体外观:

ed -- so/app.yaml <<-HERE
    ,s/SO/so/
    w
    q
HERE

另请参阅对类似问题的回答。

在您的情况下,执行管道是一个两阶段的过程:首先构建管道,然后运行它。>意思是“打开文件,截断它,并将它连接到文件描述符 1 ( stdout)”。只有这样管道才真正运行,即执行了 sed,但此时文件已经被截断。

的某些版本sed还具有-i用于就地编辑文件的参数,这使得sed行为更像ed,但不建议使用它:首先,它不支持 的所有功能ed,但更重要的是,它是GNU 的非标准化专有扩展sed,不适用于许多非 GNU 系统。自从我使用非 GNU 系统已经有一段时间了,但最后一次我使用了一个,Solaris、OpenBSD、HP-UX 和 IBM AIX 都不sed支持该-i参数。

于 2009-04-06T19:58:27.377 回答
3

我相信将输出重定向到您正在编辑的同一个文件会导致您的问题。

您需要将标准输出重定向到某个临时文件,并在 sed 完成后用临时文件覆盖原始文件。

于 2009-04-06T19:03:34.000 回答