![剪切一个文件的最后两行并重复附加到另一个文件中](https://linux22.com/image/950543/%E5%89%AA%E5%88%87%E4%B8%80%E4%B8%AA%E6%96%87%E4%BB%B6%E7%9A%84%E6%9C%80%E5%90%8E%E4%B8%A4%E8%A1%8C%E5%B9%B6%E9%87%8D%E5%A4%8D%E9%99%84%E5%8A%A0%E5%88%B0%E5%8F%A6%E4%B8%80%E4%B8%AA%E6%96%87%E4%BB%B6%E4%B8%AD.png)
我尝试使用以下命令剪切文件的最后两行并将其附加到新文件中
tail -n -2 file1 >> file2 && head -n -2 file1 > tmp && mv tmp file1
每次手动执行上述代码时,最后两行文件1剪切并附加到文件2。但是,最好的方法是什么来自动执行此操作,直到文件1没有更多条目可以删减吗?
或者您是否有以完全不同的方式做到这一点?
答案1
在我看来,使用以下方法以相反的顺序阅读两行会更简单tac
tac file1 | while IFS= read -r a && IFS= read -r b; do printf '%s\n%s\n' "$b" "$a"; done >> file2
(当剩余行数少于 2 行时,此操作将终止file1
- 谢谢u/artur meinild) 或者
tac file1 | sed -E '$!N;s/(.*)\n(.*)/\2\n\1/' >> file2
file1
(即使行数是奇数,它也会持续到1 的末尾)。
或者使用 GNU 的类似方法parallel
:
tac file1 | parallel -N2 "printf '%s\n'" '{2}' '{1}' >> file2
- 如果你想使用 sed,但又像 while 循环版本那样忽略末尾的奇数行,则将其更改为
sed -nE '$!N;s/(.*)\n(.*)/\2\n\1/p'
仅在成功替换时打印
答案2
这是适合初学者的版本,使用带有 while 循环的脚本,易于阅读和理解:
#!/bin/bash
# Do this operation as long as file1 has content
while [[ -n $(cat file1) ]]
do
# Put the 2 last lines of file1 in file2
tail -n -2 file1 >> file2
# Remove the last 2 lines of file1
head -n -2 file1 > tmp && mv -f tmp file1
done
# If you want to remove the empty file1
# rm -f file1
即使file1
行数为奇数,此解决方案仍然有效(那么 的第一行将file1
是 的最后一行file2
)。
答案3
好的,谢谢你们的建议。我尝试了一整天,在一些代码上遇到了困难,但最终我找到了解决方案。你们的想法是什么...我做了一个类似于 Arthur Meinild 提到的until循环。
until ! [ -s file_tmp ]; do
tail -n -2 file_tmp >> file.tmp && seq 2 | xargs -i sed -i -e '$d' file_tmp
done
rm file_tmp && cat file.tmp >> file
rm file.tmp
我曾用 head 代替 sed 来解决,但 head 的磁盘 io 负担更重。上面的 steeldriver 版本对我来说似乎也很有趣,但目前我将采用 sed 方式 :)
答案4
您可以使用三个命令来完成此操作。
(seq 10 提供了示例输入文件)
seq 10 | sed -n '1~2p' | tac > odds
seq 10 | sed -n '2~2p' | tac > evens
awk '{getline line < "evens"; print $0; print line}' odds
9
10
7
8
5
6
3
4
1
2