我正在尝试使用 grep -v 或 sed 从文件中删除一行,但问题是结果中的行数在删除后仍然相同。
$ grep $'\t59116613\t' ../chr/19.TB0002183.all.vcf
19 59116613 . T C 20.3144 . DP=42;VDB=0.566336;SGB=-0.651104;RPB=0.504878;MQB=0.0279668;MQSB=0.943468;BQB=0.362091;MQ0F=0;ICB=1;HOB=0.5;AC=1;AN=2;DP4=21,13,2
$ grep -v $'\t59116613\t' ../chr/19.TB0002183.all.vcf | wc -l
108067
$ wc -l ../chr/19.TB0002183.all.vcf
108067
答案1
当行计数给出意外结果时,我们应该检查每个文本处理实用程序是否以相同的方式理解行的含义。这通常可以归结为两个问题:
1) 文件转换问题:使用哪些字符作为 EOL(行尾,又称换行符或换行符)?它可能是\r
、\n
、 或 ,\r\n
具体取决于操作系统。
2) 最后一行是否也以 EOL 结束?如果不是,文本处理实用程序如何处理它?
在这种情况下,第二个问题导致了解释。
算什么wc -l
?
直接来自手册页:
-l, --lines 打印换行数
显然,如果最后一行不是以换行符结尾,则不计算最后一行,即结果比实际行数少一行。
产生什么grep
?
grep
以换行符终止每个输出行。我在文档中没有找到它,只是测试了它。
我们现在可以进行测试来解释问题中描述的行为:
- 让我们创建一个包含 3 行但没有尾随换行符的测试文件
echo -ne "first\nsecond\nthird" > 3lines.txt
- 让我们检查最后一个字符:
tail -1 3lines.txt | od -c
好吧,没有“\n”。
wc -l < 3lines.txt
输出为:2(最后一行未计算在内,因为缺少最后一个换行符)
- 通过 grep 传递所有行
grep . < 3lines.txt | wc -l
输出为 3(所有行均已计数,因为没有丢失换行符)
- 仅过滤掉一行(可以是任何行)
grep -v first < 3lines.txt | wc -l
输出为 2(再次计算所有行)。