我有一个相当大的 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
所有字段。 $0
true
答案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
。