如何仅保留文件的每第 n 行

如何仅保留文件的每第 n 行

我有一个相当大的 CSV 文件 (75MB)。我只是想制作它的图表,所以我真的不需要所有的数据。

重新措辞:我想删除 n 行,然后保留一行,然后删除 n 行,依此类推。

所以如果文件如下所示:

Line 1
Line 2
Line 3
Line 4
Line 5
Line 6

并且 n=2,则输出为:

Line 3
Line 6

似乎sed可以做到这一点,但我还没弄清楚怎么做。bash 命令是理想的选择,但我愿意接受任何解决方案。

答案1

~ $ awk 'NR == 1 || NR % 3 == 0' yourfile
Line 1
Line 3
Line 6

NR(记录数) 变量是记录行数,因为默认行为是RS(记录分隔符) 的新行。在 awk 的默认格式中,模式和操作是可选的'pattern {actions}'。当我们只给出模式部分时,就会写入模式条件的awk所有字段。 $0true

答案2

sed也可以这样做:

$ sed -n '1p;0~3p' input.txt
Line 1
Line 3
Line 6

man sed解释~为:

first~step 从第一行开始匹配每 step 行。例如,“sed -n 1~2p”将打印输入流中的所有奇数行,地址 2~5 将匹配从第二行开始的每五行。first 可以为零;在这种情况下,sed 的操作就像它等于 step 一样。(这是一个扩展。)

答案3

Perl也可以这样做:

while (<>) {
    print  if $. % 3 == 1;
}

该程序将打印输入的第一行,然后打印每三行。

稍微解释一下,<>这是行输入运算符,在像这样的循环中使用时,它会遍历输入行while。特殊变量$.包含迄今为止读取的行数,%是模数运算符。

-n使用和开关,可以将该代码写得更紧凑,成为一行代码-e

perl -ne 'print if $. % 3 == 1'  < input.txt  > output.txt

-e开关将一段 Perl 代码作为命令行参数来执行,同时该-n开关隐式地将代码包装在while循环中,如上所示。


编辑:要真正获得示例中的第 1、3、6、9 行,而不是第 1、4、7、10 行,如我最初假设您想要的那样,请将其替换$. % 3 == 1$. == 1 or $. % 3 == 0

答案4

纯 bash 中不产生进程的解决方案是:

{ for f in {1..2}; do read line; done;
  while read line; do
    echo $line;
    for f in {1..2}; do read line; done;
  done; } < file

第一行跳过文件开头的2行,然后while打印下一行并再次跳过2行。

如果您的文件较小,这是一种非常有效的工作方式,因为它不会启动进程。如果您的文件很大,则sed应该使用 ,因为它在处理 io 方面比 更高效bash

相关内容