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

Com*_*ish 87 bash

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

改写:我想删除 n 行,然后保留一行,然后删除 n 行,依此类推。

因此,如果文件如下所示:

Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
Run Code Online (Sandbox Code Playgroud)

并且 n=2,那么输出将是:

Line 3
Line 6
Run Code Online (Sandbox Code Playgroud)

似乎sed可以做到这一点,但我一直无法弄清楚如何做到这一点。bash 命令是理想的,但我愿意接受任何解决方案。

Sel*_*lug 143

~ $ awk 'NR == 1 || NR % 3 == 0' yourfile
Line 1
Line 3
Line 6
Run Code Online (Sandbox Code Playgroud)

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

  • 多亏了默认值,你甚至不需要那么多:`awk 'NR == 1 || NR % 3 == 0'` (8认同)
  • 小心解释为什么会这样?这样如果有人想稍微调整一下,那么希望你的解释能帮助他们这样做 (4认同)

kev*_*kev 63

sed 也可以这样做:

$ sed -n '1p;0~3p' input.txt
Line 1
Line 3
Line 6
Run Code Online (Sandbox Code Playgroud)

man sed解释~为:

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

  • 你能解释一下这个命令吗? (6认同)

Ilm*_*nen 23

Perl也可以这样做:

while (<>) {
    print  if $. % 3 == 1;
}
Run Code Online (Sandbox Code Playgroud)

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

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

使用-n-e开关,可以将此代码更紧凑地编写为单行代码:

perl -ne 'print if $. % 3 == 1'  < input.txt  > output.txt
Run Code Online (Sandbox Code Playgroud)

所述-e交换机将一块Perl代码以执行作为命令行参数,而-n开关隐含在一个包装了代码while如上所示的一个环路。


编辑:要真正得到线1,3,6,9,...作为例子,而不是线1,4,7,10,......我先假设你想,替换$. % 3 == 1$. == 1 or $. % 3 == 0


小智 7

如果你想用Bash脚本来做,你可以尝试:

#!/bin/sh

echo Please enter the file name
read fname
echo Please enter the Nth lines that you want to keep
read n

exec<$fname
value=0
while read line
do
    if [ $(( $value % $n )) -eq 0 ] ; then
        echo -e "$line" >> new_file.txt
    fi
        let value=value+1 
done
echo "Check the 'new_file.txt' that has been created in this directory";
Run Code Online (Sandbox Code Playgroud)

将其另存为“read_lines.sh”并记住为 bash 文件授予 +x 权限。

chmod +x ./read_lines.sh
Run Code Online (Sandbox Code Playgroud)


jfg*_*956 5

不产生进程的纯 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
Run Code Online (Sandbox Code Playgroud)

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

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


Cae*_*sar 5

GNU coreutils split 可以做到这一点,例如:

seq 100 | split -n r/3/3
Run Code Online (Sandbox Code Playgroud)

解释:split -n r/i/n将取每行 k (从 0 开始计数),其中(k % n) + 1 = i.

如果这是一个 CSV 文件并且您需要保留标题,split -n r/1/3就可以了。