删除重复行并覆盖同一命令中的文件

时间:2016-06-11 20:47:02

标签: bash awk

我正在尝试从文件中删除重复的行并更新文件。出于某种原因,我必须将其写入新文件并替换它。这是唯一的方法吗?

awk '!seen[$0]++' .gitignore > .gitignore

awk '!seen[$0]++' .gitignore > .gitignore_new && mv .gitignore_new .gitignore

3 个答案:

答案 0 :(得分:11)

重定向到与输入文件相同的输出文件,如:

awk '!seen[$0]++' .gitignore > .gitignore

将以空文件结束。这是因为使用>运算符,shell将在命令执行之前打开并截断文件。含义您将丢失所有数据。

使用较新版本的GNU awk,您可以使用-i inplace选项编辑文件

awk -i inplace '!seen[$0]++' .gitignore

如果您没有最新版本的GNU awk,则需要创建一个临时文件:

awk '!seen[$0]++' .gitignore > .gitignore.tmp
mv .gitignore.tmp .gitignore

另一种方法是使用moreutils中的sponge程序:

awk '!seen[$0]++' .gitignore | sponge .gitignore

sponge将浸泡所有stdinput并在此之后打开输出文件。这有效地保留了输入文件的完整性,然后再写入。

答案 1 :(得分:1)

托马斯,我认为问题在于你是在阅读它并用相同的命令写它。这就是你必须先放入临时文件的原因。

>覆盖,所以你使用正确的重定向运算符

  
      
  • 将命令的输出重定向到磁盘上的文件。注意:如果文件已经存在,它将被删除并覆盖而不会发出警告,因此   小心。
  •   
     

示例:ps -ax> processes.txt使用ps命令获取列表   系统上运行的进程,并将输出存储在名为的文件中   processes.txt

答案 2 :(得分:-2)

是的,因为如果你不这样做,即使在awk进程开始之前,shell也会创建文件描述符并截断.gitignore。