该文件最初是
$cat so/app.yaml
application: SO
...
Run Code Online (Sandbox Code Playgroud)
我运行以下命令.我得到一个空文件.
$sed s/SO/so/ so/app.yaml > so/app.yaml
$cat so/app.yaml
$
Run Code Online (Sandbox Code Playgroud)
如何使用SED编辑文件而不是给我一个空文件?
所述>管道中用来将打开输出文件时的配管都成立,命令执行之前即 因此,输入文件在sed执行之前被截断.这是所有shell重定向的问题,而不仅仅是sed.
Sheldon Young的答案显示了如何使用就地编辑.
您正在使用错误的工具来完成工作.sed是一个流编辑器(这就是为什么它被称为sed),因此它用于在管道中进行流中的流编辑.edOTOH是一个文件编辑器,它可以做任何事情都sed可以做,除了它适用于文件而不是流.(实际上,它是相反的方式:ed是原始实用程序,sed是一个克隆,可以避免为流创建临时文件.)
ed非常有用sed(因为sed它只是一个克隆),但有一个重要区别:你可以在文件中移动,但你不能在流中移动.所以,在所有的命令ed采取讲述了一个地址参数ed,其中,在该文件中应用的命令.在您的情况下,您希望在文件中的任何位置应用命令,因此地址参数只是,因为a,b"从行a到行b"和默认a值为1(文件开头)和默认b值为$(结束时) -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
Run Code Online (Sandbox Code Playgroud)
另见我对类似问题的回答.
在您的情况下发生的是,执行管道是一个两阶段的过程:首先构建管道,然后运行它.>表示"打开文件,截断文件,并将其连接到filedescriptor 1(stdout)".只有这样才能实际运行管道,即执行sed,但此时文件已被截断.
有些版本sed还有一个-i用于就地编辑文件的参数,这使得sed行为更像ed,但使用它是不可取的:首先,它不支持所有功能ed,但更重要的是,它是GNU的非标准化专有扩展sed,不适用于许多非GNU系统.我使用非GNU系统已经有一段时间了,但最后我使用了一个,Solaris和OpenBSD,HP-UX和IBM AIX都不sed支持该-i参数.