59

我正在尝试在 shell 脚本中使用 sed 命令,我想在其中删除 read 的STARTremoveThisComment行和 read 的行removeThisCommentEND

当我将它复制到一个新文件时,我可以做到这一点

sed 's/STARTremoveThisComment//' > test

但是如何通过使用相同的文件作为输入和输出来做到这一点?

4

5 回答 5

93

sed -i(或扩展版本,--in-place)将自动化通常使用不太高级的实现完成的过程,将输出发送到临时文件,然后将其重命名回原始文件。

-i用于就地编辑,您还可以提供备份后缀以保留原始副本:

sed -i.bak fileToChange
sed --in-place=.bak fileToChange

这两个都将原始文件保留在fileToChange.bak.

请记住,就地编辑可能并非在所有sed实现中都可用,但它在 GNUsed中的,根据您的标签,它应该在所有 Linux 变体上都可用。

如果您使用的是更原始的实现,则可以使用以下内容:

cp oldfile oldfile.bak && sed 'whatever' oldfile >newfile && mv newfile oldfile
于 2012-05-31T08:00:43.493 回答
11

You can use the flag -i for in-place editing and the -e for specifying normal script expression:

sed -i -e 's/pattern_to_search/text_to_replace/' file.txt

To delete lines that match a certain pattern you can use the simpler syntax. Notice the d flag:

sed -i '/pattern_to_search/d' file.txt
于 2015-03-23T18:52:36.467 回答
5

You really should not use sed for that. This question seems to come up ridiculously often, and it seems very strange that it does, since the general solution is so trivial, it seems bizarre that people want to know how to do it in sed, and in python, and in ruby, etc. If you want to have a filter operate on an input and overwrite it, use the following simple script:

#!/bin/sh -e
in=${1?No input file specified}
mv $in ${bak=.$in.bak}
shift
"$@" < $bak > $in

Put that in your path in an executable file name inline, and then the problem is solved in general. For example:

inline input-file sed -e s/foo/bar/g

Now, if you want to add logic to keep multiple backups, or if you have some options to change the backup naming scheme, or whatever, you fix it in one place. What's the command line option to get 1-up counters on the backup file when processing a file in-place with perl? What about with ruby? Is the option different for gnu-sed? How does awk handle it? The whole friggin' point of unix is that tools do one thing only. Handling logic for backup files is a second thing, and needs to be factored out. If you are implementing a tool, do not add logic to create backup files. Tell your users to use a 2nd tool for that. Integration is bad. Modularity is good. That is the unix way.

Notice that this script has several problems. The permissions/mode of the input file may be changed, for example. I'm sure there are innumerable other issues. However, by putting the backup logic in a wrapper script, you localize all of these issues and don't have to worry that sed overwrites the files and changes mode, while python keeps the file in place and does not change the inode (I made up those two cases, the point being that not all tools will use the same logic, while the wrapper script will.)

于 2012-05-31T13:07:18.447 回答
0

据我所知,不可能使用相同的文件进行输入和输出。虽然一种解决方案是制作一个将其保存到另一个文件的 shell 脚本,但删除旧的输入并将输出重命名为输入文件名。

sed -e s/try/this/g input.file > output.file;mv output.file input.file
于 2012-05-31T07:59:27.003 回答
0

I suggest using sponge

sponge reads standard input and writes it out to the specified file. Unlike a shell redirect, sponge soaks up all its input before writing the output file. This allows constructing pipelines that read from and write to the same file.

cat test | sed 's/STARTremoveThisComment//' | sponge test
于 2019-07-01T16:59:10.480 回答