我可以让 `cut` 就地更改文件吗?

Han*_*Gay 20 shell io-redirection cut files

man页面并没有给我太大希望,但我希望它是一个未记录的(和/或特定于 GNU 的)功能。

Kje*_*sen 28

来自 ubuntu(以及debian)的moreutils包有一个名为 的程序,它也可以解决您的问题。sponge

从人海绵:

海绵读取标准输入并将其写出到指定的文件。与 shell 重定向不同,海绵在打开输出文件之前吸收所有输入。这允许限制读取和写入同一文件的管道。

这会让你做这样的事情:

cut -d <delim> -f <fields> somefile | sponge somefile
Run Code Online (Sandbox Code Playgroud)


Gil*_*il' 17

你不能。要么使用 ed 或 GNU sed 或 perl,要么做他们在幕后做的事情,即为内容创建一个新文件。

ed, 便携的:

ed foo <<EOF
1,$s/^\([^,]*\),\([^,]*\),\([^,]*\).*/\1,\3/
w
q
EOF
Run Code Online (Sandbox Code Playgroud)

GNU sed:

sed -i -e 's/^\([^,]*\),\([^,]*\),\([^,]*\).*/\1,\3/' foo
Run Code Online (Sandbox Code Playgroud)

珀尔:

perl -i -l -F, -pae 'print @F[1,3]' foo
Run Code Online (Sandbox Code Playgroud)

cut, 创建一个新文件(推荐,因为如果你的脚本被中断,你可以再次运行它):

cut -d , -f 1,3 <foo >foo.new &&
mv -f foo.new foo
Run Code Online (Sandbox Code Playgroud)

cut, 替换文件到位(保留 的所有权和权限foo,但需要防止中断):

cp -f foo foo.old &&
cut -d , -f 1,3 <foo.old >foo &&
rm foo.old
Run Code Online (Sandbox Code Playgroud)

我建议使用一种cut基于 - 的方法。这样您就不必依赖任何非标准工具,您可以使用最适合工作的工具,并控制中断时的行为。

  • @GypsyCosmonaut 不,这不是“更好”。它更脆弱。它唯一的好处是打字时间更短。您的方法的主要问题是,如果在处理输入文件或写入输出时发生错误,数据将丢失。它也不适用于二进制数据:输出将在第一个空字节处被截断。即使是文本文件,它也会从文件末尾删除空行。对于大文件,它可能会失败,因为数据必须作为字符串存储在 shell 的内存中(请记住,如果发生这种情况,数据将丢失)。 (2认同)
  • @LoMaPh 确实,我不知道为什么要重命名旧文件:与重命名新文件相比,它没有任何优势。它也更简单,因为您不需要步骤 `rm foo`。而且你不应该调用 `rm foo`,因为 `mv foo.new foo` 是原子的:它会删除旧版本并同时放置新版本。 (2认同)

Ste*_*n D 9

我认为cut单独使用是不可能的。我在 man 或 info 页面中找不到它。你可以做一些事情,比如

mytemp=$(mktemp) && cut -d" " -f1 file > $mytemp && mv $mytemp file
Run Code Online (Sandbox Code Playgroud)

mktemp使您成为一个相对安全的临时文件,您可以将cut输出传输到该文件中。