【问题标题】:How to cat a file and create a new file with the same name without creating a new one file | Unix Korn shell [duplicate]如何在不创建新文件的情况下cat文件并创建具有相同名称的新文件| Unix Korn shell [重复]
【发布时间】:2018-07-03 21:45:48
【问题描述】:

有一种方法可以对文件进行分类,通过某些内容对其进行过滤,然后输出一个具有相同名称的新文件?我正在这样做,我得到一个空文件,但如果我用不同的文件名创建它是有效的。我不想创建新文件。

例子:

File="My_test_file.txt"
cat ${File} | grep -v "test" > ${File}

那样不行,我必须创建另一个文件才能使其工作,如下所示:

File="My_test_file.txt"
cat ${File} | grep -v "test" > ${File}.tmp

有什么想法吗?

【问题讨论】:

  • 我认为目前的任何一个答案都没有解决“为什么”。解释一下:管道的所有部分并行执行。因此,当输入中的cat 仍在运行(或者,可能只是启动但根本还没有运行)时,打开文件以进行输出(因此被截断!)。
  • (顺便说一句,cat ${File} 最好写成cat "$File":在这种情况下,花括号对正确性没有任何作用,而缺少双引号会使内容容易发生字符串拆分和全局扩展, 所以如果你有一个带空格的文件名就行不通了。比这更好的是完全取消 cat 并让 grep 直接从输入文件中读取)。
  • @CharlesDuffy 我同意这个问题的答案没有解释原因,但你的引文中接受的答案并没有说明如何,这是 OP 想知道的。
  • @jeff6times7,我添加了三个(错误,现在是四个)额外的副本,专门关注“如何”,将它们放在关注“为什么”的之上。

标签: shell unix cat createfile


【解决方案1】:

有一个名为 moreutils 的包,其中包含用于此目的的工具 sponge

grep -v test foo.txt | sponge foo.txt

如果安装工具不是一个选项,你可以实现一个幼稚的版本,首先将所有数据读入内存,然后最后将其写出来:

#!/bin/sh

sponge() (
  var="$(cat; printf x)"
  printf '%s' "${var%x}" > "$1"
)

grep -v test foo.txt | sponge foo.txt

【讨论】:

  • 可能值得指出为什么这有效(具体来说,它消耗所有可用的输入,缓冲它,打开输出文件之前)。
【解决方案2】:

您尝试使用catgrep -v 执行的操作可以使用sed -i '/pattern/d' 轻松完成,并且还可以内联保存更改:

sed -i.bak '/test/d' "$file"

【讨论】:

  • 它可以工作,但我需要这样做:sed -i.bak '/test/d' "$file" > "$file" 我必须创建输出的新文件并覆盖现有文件,我用你的命令做到了,正在为我创建一个空文件,我将不得不做类似sed -i.bak '/test/d' "$file" > "${file}.tmp"
  • @JavierSalas 不,sed -i 为您修改文件。不要将其重定向到任何地方。
  • @anubhava 不幸的是 sed -i 选项在我的 shell 中不起作用sed: illegal option -- i
  • -i 也出现在 BSD sed 中,当然 gnu sed 也有。您的操作系统和 sed 版本是什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多