如何在命令中使用文件并将输出重定向到同一文件而不截断?
基本上,我想从文件中以输入文本为输入,从该文件中删除一行,然后将输出发送回同一文件。如果这样可以使它变得更清晰。
grep -v 'seg[0-9]\{1,\}\.[0-9]\{1\}' file_name > file_name
但是,当我这样做时,我最终会得到一个空白文件。 有什么想法吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
使用 Sponge 用于此类任务。它的一部分是莫比尔。
尝试此命令:
Use sponge for this kind of tasks. Its part of moreutils.
Try this command:
您不能这样做,因为Bash首先处理重定向,然后执行命令。因此,到Grep查看File_name时,它已经为空了。您可以使用临时文件。
这样,请考虑使用
mktemp
创建 tmpfile ,但请注意,它不是POSIX。You cannot do that because bash processes the redirections first, then executes the command. So by the time grep looks at file_name, it is already empty. You can use a temporary file though.
like that, consider using
mktemp
to create the tmpfile but note that it's not POSIX.改用SED:
Use sed instead:
尝试这个简单的文件,
这次您的文件不会空白:),您的输出也印在您的终端。
try this simple one
Your file will not be blank this time :) and your output is also printed to your terminal.
这是非常可能的,您只需要确保在编写输出时,将其写入另一个文件。这可以通过在打开文件描述符后删除文件来完成,但是在写信给该文件描述符后:
或逐条划线,以更好地理解它:
这仍然是一件风险的事情,因为如果命令无法正常运行,则您' LL丢失文件内容。如果命令返回非零退出代码,可以通过还原文件来缓解这种情况:
我们还可以定义一个shell函数以使其更易于使用:
示例:
另外,请注意,这将保留原始文件的完整副本(直到直到第三个文件描述符已关闭)。如果您使用的是Linux,并且要处理的文件太大,无法在磁盘上进行两次适合,则可以查看此脚本在未分配已经处理过的块的同时,将文件将文件交给指定的命令block块。与往常一样,请阅读使用页面中的警告。
This is very much possible, you just have to make sure that by the time you write the output, you're writing it to a different file. This can be done by removing the file after opening a file descriptor to it, but before writing to it:
Or line by line, to understand it better :
It's still a risky thing to do, because if COMMAND fails to run properly, you'll lose the file contents. That can be mitigated by restoring the file if COMMAND returns a non-zero exit code :
We can also define a shell function to make it easier to use :
Example :
Also, note that this will keep a full copy of the original file (until the third file descriptor is closed). If you're using Linux, and the file you're processing on is too big to fit twice on the disk, you can check out this script that will pipe the file to the specified command block-by-block while unallocating the already processed blocks. As always, read the warnings in the usage page.
您不能将重定向运算符(
>
或>>
)用于同一文件,因为它具有更高的优先级,并且会在之前创建/截断文件。该命令甚至被调用。为了避免这种情况,您应该使用适当的工具,例如Tee
,Sponge
,sed -i
或任何其他可以将结果写入文件的工具(例如分类文件-O文件
)。基本上,将输入重定向到同一原始文件没有意义,您应该使用适当的原位编辑器为此,例如Ex Editor(VIM的一部分):
where:
'+CMD'
/<代码> -c - 运行任何EX/VIM命令g/datter/d
- 使用 global (help:g
)-s
- 静音模式(man ex
):写
and:退出
命令您可以使用
SED> SED> SED
实现相同(如已经显示的那样在其他答案中),但是在场(-i
)是非标准的freebsd扩展程序(Unix/linux之间的工作方式可能有所不同),并且基本上是 s s tream ed itor,而不是文件编辑器。请参阅: ex模式有任何实际用途吗?You can't use redirection operator (
>
or>>
) to the same file, because it has a higher precedence and it will create/truncate the file before the command is even invoked. To avoid that, you should use appropriate tools such astee
,sponge
,sed -i
or any other tool which can write results to the file (e.g.sort file -o file
).Basically redirecting input to the same original file doesn't make sense and you should use appropriate in-place editors for that, for example Ex editor (part of Vim):
where:
'+cmd'
/-c
- run any Ex/Vim commandg/pattern/d
- remove lines matching a pattern using global (help :g
)-s
- silent mode (man ex
)-c wq
- execute:write
and:quit
commandsYou may use
sed
to achieve the same (as already shown in other answers), however in-place (-i
) is non-standard FreeBSD extension (may work differently between Unix/Linux) and basically it's a stream editor, not a file editor. See: Does Ex mode have any practical use?由于这个问题是搜索引擎中的最佳结果,因此这里是基于 https://serverfault.com/a/547331 使用子壳代替
Sponge
(通常不是像OS X这样的香草安装的一部分):一般情况是:
编辑,上述解决方案有一些警告:
printf'%s'&lt; string&gt;
应代替echo echo&lt; string&gt;
,以便包含-n
don'的文件t导致不希望的行为。x
的后缀字符附加到输出,然后通过临时变量的参数扩展喜欢$ {v%x}
。$ V
踩踏任何现有变量$ v
的值,因此我们应该在括号中嵌套整个表达式以保留上一个值。null
。我通过调用dd if =/dev/Zero bs = 1 count = 1&gt;&gt来验证这一点。 file_name
并使用cat file_name |在十六进制中查看它| xxd -p
。但是echo $(cat file_name)| XXD -P
已剥离。 So this answer should not be used on binary files or anything using unprintable characters, as一般解决方案(Albiet稍慢,内存更大,仍在剥离无法打印的字符)是:
测试来自 https:// https:// https:// askubuntu.com/a/752451 :
应该打印:
而呼叫
cat file_uniquely_named.txt&gt; file_uniquely_named.txt
在当前壳中:打印一个空字符串。
我尚未在大文件(可能超过2或4 GB)上测试过。
我已经从 kos 。
Since this question is the top result in search engines, here's a one-liner based on https://serverfault.com/a/547331 that uses a subshell instead of
sponge
(which often isn't part of a vanilla install like OS X):The general case is:
Edit, the above solution has some caveats:
printf '%s' <string>
should be used instead ofecho <string>
so that files containing-n
don't cause undesired behavior.x
to the output and remove it on the outside via parameter expansion of a temporary variable like${v%x}
.$v
stomps the value of any existing variable$v
in the current shell environment, so we should nest the entire expression in parentheses to preserve the previous value.null
from the output. I verified this by callingdd if=/dev/zero bs=1 count=1 >> file_name
and viewing it in hex withcat file_name | xxd -p
. Butecho $(cat file_name) | xxd -p
is stripped. So this answer should not be used on binary files or anything using unprintable characters, as Lynch pointed out.The general solution (albiet slightly slower, more memory intensive and still stripping unprintable characters) is:
Test from https://askubuntu.com/a/752451:
Should print:
Whereas calling
cat file_uniquely_named.txt > file_uniquely_named.txt
in the current shell:Prints an empty string.
I haven't tested this on large files (probably over 2 or 4 GB).
I have borrowed this answer from Hart Simha and kos.
一个班轮替代方案 - 将文件的内容设置为可变:
One liner alternative - set the content of the file as variable:
以下将完成与
Sponge
所做的事情相同的事情,而无需moreutils
:- andural-source =/dev/dev/Zero part Tricks <代码> shuf
完全不进行任何改组,因此可以在不更改的情况下缓冲输入。但是,出于性能原因,最好最好使用临时文件。因此,这是我写的一个功能,它将以一种广义的方式为您做到这一点:
The following will accomplish the same thing that
sponge
does, without requiringmoreutils
:The
--random-source=/dev/zero
part tricksshuf
into doing its thing without doing any shuffling at all, so it will buffer your input without altering it.However, it is true that using a temporary file is best, for performance reasons. So, here is a function that I have written that will do that for you in a generalized way:
在我面临的大多数情况下,这确实做得很好:
请注意,
$(…)
strips trailing newlines,&lt;&lt;&lt;&lt;
/em>最终的新线,因此总体而言,结果是神奇的令人满意的。(在
MAN BASH
中查找“此处的字符串”,如果您想了解更多。)完整示例:
这不会截断文件并产生:
请注意,为了清楚起见,我在这里使用了一个函数可扩展性,但这不是必需的。
一个常见的用户酶是JSON Edition:
Tures:
This does the trick pretty nicely in most of the cases I faced:
Note that while
$(…)
strips trailing newlines,<<<
ensures a final newline, so generally the result is magically satisfying.(Look for “Here Strings” in
man bash
if you want to learn more.)Full example:
This does not truncate the file and yields:
Note that I used a function here for the sake of clarity and extensibility, but that’s not a requirement.
A common usecase is JSON edition:
This yields:
还有
ed
(作为sed -i
的替代方案):There's also
ed
(as an alternative tosed -i
):您可以将slurp与posix awk一起使用:
You can use slurp with POSIX Awk:
Example
我通常使用 Tee 程序来做到这一点:
它可以创建和删除临时性。
I usually use the tee program to do this:
It creates and removes a tempfile by itself.
尝试一下
Try this