首先准备一个
rumenz.txt文件:
$ cat rumenz.txt
1 rumenz.com
2 rumenz
3 入门
4 小站
5 入门小站
6 小站入门
7 门小
8 入站
9 123
10 rumenxiaozhan
如上面的输出所示,我们的
rumenz.txt包含十行。现在,假设我们要从
rumenz.txt文件中删除最后三行 (n=3) 。在本教程中,我们将使用四种技术解决问题:
head命令wc和sed 命令tac和sed命令awk命令head命令
使用head命令,我们可以通过在连字符(-)后面传递一个数字以及-n选项(例如-n -x来打印文件中除最后x行之外的所有行因此,我们可以使用此选项以直接的方式解决我们的问题:
$ head -n -3 rumenz.txt
1 rumenz.com
2 rumenz
3 入门
4 小站
5 入门小站
6 小站入门
7 门小
但是
head命令在标准输入中打印结果。我们可以通过临时文件将结果保存回output.txt:
$ head -n -3 rumenz.txt > tmp.txt && mv tmp.txt output.txt
wc和sed命令使用
sed命令及其地址范围,我们可以快速删除文件中从给定行号开始到最后一行的行:
sed 'GIVEN`LINE`NO, $d' input_file
例如,让我们从第5行删除直到
rumenz.txt的结尾:
$ sed '5,$d' rumenz.txt
1 rumenz.com
2 rumenz
3 入门
4 小站
然而,我们的问题是从输入文件中删除最后三行。由于我们的输入文件有十行,
sed命令:sed 8,$d rumenz.txt将是解决问题的方法。这样,问题就变成了如何计算第一个要删除的行号
8。现在,是时候介绍
wc命令了。使用带有_-l_选项的wc命令,我们可以轻松获得文件中的总行数 (TOTAL):
$ wc -l rumenz.txt
10 rumenz.txt
此外,我们可以通过计算
TOTAL – n + 1来获得要删除的第一个行号。在我们的例子中,我们有n=3:
$ echo $(($(wc -l <rumenz.txt)-3+1))
8
让我们仔细看看上面的命令:
wc -l <rumenz.txt:这里我们将 rumenz.txt 文件重定向到 stdin 以跳过输出中的文件名$(wc -l <rumenz.txt):我们使用命令替换来捕获TOTAL结果$((TOTAL – 3+1)):算术扩展将计算数学表达式现在,让我们将这两个部分组装在一起并尝试解决我们的问题:
$ sed '$(($(wc -l <rumenz.txt)-3+1)),$d' rumenz.txt
sed: -e expression #1, char 2: unknown command: `('
上面的错误原因是因为bash扩展和命令替换不会在单引号之间扩展。
让我们将
sed命令中的单引号改为双引号并再次测试:
$ sed "$(($(wc -l <rumenz.txt)-3+1)),$ d" rumenz.txt
1 rumenz.com
2 rumenz
3 入门
4 小站
5 入门小站
6 小站入门
7 门小
如果我们使用流行的
GNUsed,我们可以使用-i选项将更改写回输入文件:
$ sed -i "$(($(wc -l <rumenz.txt)-3+1)),$ d" rumenz.txt
tac和sed命令使用
sed解决问题的难点 在于计算要删除的第一行号。但是,如果我们可以颠倒输入文件中的行顺序,问题就会变成从文件中删除前 n 行。一个简单的 sed 单行
sed 1,n d可以删除前n行。之后,如果我们再次反转线条,我们的问题就解决了。
tac命令可以反向文件中的行的顺序。也就是说,我们可以尝试通过命令tac INPUT_FILE | sed ‘1,n d’ | tac来解决我们的问题最后,让我们测试一下它是否适用于我们的示例:
$ tac rumenz.txt | sed '1,3 d' | tac
1 rumenz.com
2 rumenz
3 入门
4 小站
5 入门小站
6 小站入门
7 门小
awk命令该
AWK命令是一个功能强大的文本处理工具。我们可以让awk两次遍历输入文件来解决问题。在第一遍中,它会找出文件中的总行数,在第二遍中,我们打印我们想要保留的那些行:
$ awk -v n=3 'NR==FNR{total=NR;next} FNR==total-n+1{exit} 1' rumenz.txt rumenz.txt
1 rumenz.com
2 rumenz
3 入门
4 小站
5 入门小站
6 小站入门
7 门小
最后,让我们了解 one-liner 是如何工作的:
-v n=3:声明了一个awk变量 n=3NR==FNR{total=NR;next}:这是第一遍。在这个过程中,awk命令将当前行号保存到一个名为total的变量中。第一遍后,total变量保存了输入文件中的总行数FNR==total-n+1{exit} 1:这是第二遍。如果FNR==total-n+1,则表示我们已经到达需要删除的第一行,因此我们退出。否则,我们只打印该行。在这里非零数字1``true 并触发awk的默认操作