该文件最初是
$cat so/app.yaml
application: SO
...
我运行以下命令。我得到一个空文件。
$sed s/SO/so/ so/app.yaml > so/app.yaml
$cat so/app.yaml
$
如何使用 SED 编辑文件而不给我一个空文件?
该文件最初是
$cat so/app.yaml
application: SO
...
我运行以下命令。我得到一个空文件。
$sed s/SO/so/ so/app.yaml > so/app.yaml
$cat so/app.yaml
$
如何使用 SED 编辑文件而不给我一个空文件?
$ sed -i -e's/SO/so/' so/app.yaml
-i
手段到位。
管道中使用的>
将在管道全部设置好时打开输出文件,即在命令执行之前。因此,输入文件在执行之前被截断sed
。这是所有 shell 重定向的问题,而不仅仅是sed
.
Sheldon Young 的回答展示了如何使用就地编辑。
您为这项工作使用了错误的工具。sed
是一个流编辑器(这就是它被称为sed
的原因),所以它用于对管道中的流进行动态编辑。ed
OTOH 是一个文件编辑器,它可以做所有sed
可以做的事情,除了它适用于文件而不是流。(实际上,它是相反的:ed
是原始实用程序,并且sed
是避免为流创建临时文件的克隆。)
ed
工作方式非常相似sed
(因为sed
只是一个克隆),但有一个重要区别:您可以在文件中移动,但不能在流中移动。因此,所有命令都ed
带有一个地址参数,该参数告诉在文件中ed
的何处应用命令。在您的情况下,您希望在文件中的任何位置应用命令,因此 address 参数只是,
因为a,b
表示“从行a
到行b
”,默认为a
( 1
beginning-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
参数。
我相信将输出重定向到您正在编辑的同一个文件会导致您的问题。
您需要将标准输出重定向到某个临时文件,并在 sed 完成后用临时文件覆盖原始文件。