首先准备一个
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 门小
如果我们使用流行的
GNU
sed
,我们可以使用-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=3
NR==FNR{total=NR;next}
:这是第一遍。在这个过程中,awk
命令将当前行号保存到一个名为total
的变量中。第一遍后,total
变量保存了输入文件中的总行数FNR==total-n+1{exit} 1
:这是第二遍。如果FNR==total-n+1
,则表示我们已经到达需要删除的第一行,因此我们退出。否则,我们只打印该行。在这里非零数字1``true
并触发awk
的默认操作