我想用来paste
在原始文件“first.xls”中添加新列。我的文件:
first.xls
1
1
1
second.xls
2
2
2
我在用着:
paste -d'\t' first.xls second.xls >> first.xls
我得到
first.xls
:
1
1
1
1 2
1 2
1 2
但我想要的是
first.xls
:
1 2
1 2
1 2
我不想将其保存到我想first.xls
从头开始覆盖的新文件中。我需要这个,因为我想将新列粘贴到最后的结果中,以便每次运行脚本时添加新列
1 2 2
1 2 2
1 2 2
然后
1 2 2 2
1 2 2 2
1 2 2 2
等等...
答案1
使用海绵来自更多实用程序包裹:
paste -d'\t' first.xls second.xls | sponge first.xls
man sponge
海绵读取标准输入并将其写入指定文件。与 shell 重定向不同,sponge 在打开输出文件之前吸收所有输入。这允许限制读取和写入同一文件的管道。
答案2
我认为你一个人无法做到这paste
一点。
我会这样做:
paste -d' ' first.txt second.txt > tmpout && mv tmpout first.txt
第一次运行后的结果:
cat first.txt
1 2
1 2
1 2
第二次运行后:
cat first.txt
1 2 2
1 2 2
1 2 2
...第三次运行:
cat first.txt
1 2 2 2
1 2 2 2
1 2 2 2
答案3
替代解决方案awk
$ seq 3 > first.xls
$ seq 4 6 > second.xls
$ awk -v OFS="\t" 'NR==FNR{a[NR]=$0; next} {print a[FNR], $0 > "first.xls"}' first.xls second.xls
$ cat first.xls
1 4
2 5
3 6
$ awk -v OFS="\t" 'NR==FNR{a[NR]=$0; next} {print a[FNR], $0 > "first.xls"}' first.xls second.xls
$ cat first.xls
1 4 4
2 5 5
3 6 6
答案4
正如另一个答案所建议的,海绵是完成这项工作的正确工具!
sudo yum install moreutils
paste first.xls second.xls | sponge first.xls
使用 tee 的 bash 命令适用于小文件(<2048 行):
注意:此技巧不适用于较大的文件。
paste first.xls second.xls | tee first.xls >/dev/null
first.x second. result
1 2 1 2
1 2 1 2
1 2 1 2
此命令在两个文件上运行粘贴,然后通过管道传输到“tee”。tee 命令重新打开文件(和标准输出)以进行写入。所以它有效。 。但这有点像黑客。 。它适用于所有系统吗?这也适用于大文件吗?
在这里看到不完全相同但相关的问题: https://stackoverflow.com/questions/1569730/paste-without-temporary-files-in-unix
您的问题是您的命令打开first.xls 以同时进行写入(追加)和读取。从文件中读取数据(然后与其他文件粘贴)。然后输出数据被写入(附加)到文件中。新写入的数据被读回,导致追加——正如预期的那样。您的附加命令:
paste first.xls second.xls >> first.xls
first.x second. result
1 2 1
1 2 1
1 2 1
1 2
1 2
1 2
将重定向更改为打开覆盖也不起作用。它会导致first.xls 在读取之前被打开并擦除。你会得到一个空白列 + 2 列。覆盖而不是附加不能以不同的方式工作:
paste first.xls second.xls > first.xls
first.x second. result
1 2 2
1 2 2
1 2 2
测试更大的文件
1000行有效:
yes "1" | fmt -2 |head -1000 >1000.1
yes "2" | fmt -2 |head -1000 >1000.2
paste 1000.1 1000.2 |tee 1000.1 >/dev/null
uniq -c 1000.1
1000 1 2
10000 行我们又开始看到类似的问题:
有趣的是,我们在 2048 行之后看到了它:-) 我猜测是由磁盘缓冲区限制或管道缓冲限制引起的。 。 。
yes "1" | fmt -2 |head -10000 >10000.1
yes "2" | fmt -2 |head -10000 >10000.2
paste 10000.1 10000.2 |tee 10000.1 >/dev/null
uniq -c 10000.1
2048 1 2
7952 2