该文件最初是
$cat so/app.yaml
application: SO
...
我运行以下命令。我得到一个空文件。
$sed s/SO/so/ so/app.yaml > so/app.yaml
$cat so/app.yaml
$
如何使用SED编辑文件而不是给我一个空文件?
答案 0 :(得分:16)
$ sed -i -e's/SO/so/' so/app.yaml
-i
表示就地。
答案 1 :(得分:5)
管道中使用的>
将在管道全部设置时打开输出文件,即在命令执行之前打开输出文件。因此,输入文件在sed
执行之前被截断。这是所有shell重定向的问题,而不仅仅是sed
。
Sheldon Young的回答显示了如何使用就地编辑。
答案 2 :(得分:5)
您使用错误的工具进行工作。 sed
是一个流编辑器(这就是为什么它被称为 s ed
),因此它用于在管道中对流进行动态编辑。 ed
OTOH是一个文件编辑器,它可以执行sed
可以执行的所有操作,但它适用于文件而不是流。 (实际上,反之亦然:ed
是原始实用程序,sed
是一个克隆,可以避免为流创建临时文件。)
ed
非常类似于sed
(因为sed
只是一个克隆版),但有一个重要区别:你可以在文件中移动,但你无法四处移动在溪流中。因此,ed
中的所有命令都会使用一个地址参数来告知文件中的ed
,,其中以应用该命令。在您的情况下,您希望在文件中应用无处不在命令,因此地址参数仅为,
,因为a,b
表示“从行a
到行b
“a
的默认值为1
(文件开头),b
的默认值为$
(文件结尾) ,所以将它们都保留为“从文件开头到文件结尾”。然后是s
(替代),其余的看起来很像sed
。
因此,您的sed
命令s/SO/so/
将变为ed命令,s/SO/so/
。
而且,再次因为ed
是一个文件编辑器,更准确地说是一个交互式文件编辑器,我们还需要编写(w
)文件并退出(q
)编辑器。
这就是它的整体外观:
ed -- so/app.yaml <<-HERE
,s/SO/so/
w
q
HERE
另请参阅my answer类似的问题。
在您的情况下发生的事情是,执行管道是一个两阶段的过程:首先构造管道,然后运行它。 >
表示“打开文件,截断,并将其连接到filedescriptor 1(stdout
)”。 只有才是实际运行的管道,即执行sed,但此时文件已被截断。
某些版本的sed
也有-i
参数用于就地编辑文件,这使得sed
的行为更像ed
,但使用的是不可取:首先,它不支持ed
的所有功能,但更重要的是,它是GNU sed
的非标准化专有扩展,不适用于许多非GNU系统。我使用非GNU系统已经有一段时间了,但最后我使用了一个,Solaris和OpenBSD,HP-UX和IBM AIX sed
都不支持-i
参数。
答案 3 :(得分:3)
我相信将输出重定向到您正在编辑的同一文件会导致您的问题。
您需要将标准输出重定向到某个临时文件,并在完成sed时用临时文件覆盖原始文件。