如何从文件中删除每隔两行?


25

文件:

Data inserted into table. Total count 13
No error occurred
Data inserted into table. Total count 45
No error occurred
Data inserted into table. Total count 14
No error occurred
Data inserted into table. Total count 90
No error occurred

预期输出文件:

Data inserted into table. Total count 13
Data inserted into table. Total count 45
Data inserted into table. Total count 14
Data inserted into table. Total count 90

我希望输出看起来像这样:每隔两行将被删除,但两行之间没有间隙。


5
是否要每隔两行或包含“未发生错误”的所有行删除?如果连续两行显示“没有错误”怎么办?
图兰斯·科尔多瓦

1
@ user1598390我认为...在这种情况下,grep -v "No error occurred" file此命令应该有效... @ paul 回答了什么。在输出文件中,将没有包含“没有错误发生”这一部分的行。
pmaipmui 2015年

1
然后,该问题的标题具有误导性。
图兰斯·科尔多瓦

Answers:


36

sed

sed -e n\;d <file

使用POSIX awk

awk 'FNR%2' <file

如果您年龄较大awk(如oawk),则需要:

oawk 'NR%2 == 1' <file

ex

$ ex file <<\EX
:g/$/+d
:wq!
EX

将就地编辑文件。

  • g 标记全局命令
  • /$/ 匹配每一行
  • +d 删除下一行
  • wq! 保存所有更改

这种方法与sed方法具有相同的理想,从第1行开始删除当前行的每一行。

perl

perl -ne 'print if $. % 2' <file

perl6

perl6 -ne '.say if $*IN.ins % 2' <file
perl6 -ne '.say if ++$ % 2' <file

是的...它的工作... :) ...第一个正在工作....我也尝试了第二个..它告诉'awk:语法错误line1 awk:在第1行附近
解救

sed -en \; d <文件〜是其工作@cuonglm ...
pmaipmui 2015年

1
我猜想您n\;d不是'n;d'用来保存宝贵的字符的,而是当您不必要地使用-e开关和文件重定向时,逻辑就会消失了<
Tom Fenech

1
@Geek:这只是的较短版本sed -e 'n;d',请节省一个字符。
cuonglm

1
@Geek:n命令将模式空间写入标准输出(如果-n已使用),然后用下一行替换模式空间。这是每条奇数行将由n,偶数行打印,然后读入模式空间,但立即通过d命令` 删除。
cuonglm

62

通过删除第二行来解决此问题可能很容易出错(例如,当进程有时生成两条有意义的行而不是一行时)。过滤掉垃圾可能更好:

grep -v "No error occurred" file

它可以作为过滤器运行,您可以在此处添加更多垃圾模式并改善结果。


9
+1指出有时第二行很重要!
卡兹·沃尔夫

12

关于这个问题,使用GNU sed

sed '0~2d' file

会删除第二行,但我想按内容提供过滤行:

sed '/Data/! d' file

或结果相同

sed '/No error/d' file

sed'/ No error / d'文件〜提供所需的输出@Costas
pmaipmui 2015年

5
需要注意的是最后两个被卷积书写方式grep Datagrep -v 'No error'
斯特凡Chazelas

5

这是一种使用方法sed

sed -n 'p;n' filename

GNU的另一种方式sed

sed -n '1~2p' filename

以上命令的输出:

Data inserted into table. Total count 13
Data inserted into table. Total count 45
Data inserted into table. Total count 14
Data inserted into table. Total count 90

你说的是什么意思shortest way using sed
cuonglm

g指挥的原因是什么?sed -n 'p;n'足够。
Costas

@cuonglm:我的意思是说简单的方法。顺便说一下,删除了这个词。:)
serenesat

@Costas:谢谢!刚刚检查过,它没有工作g。从命令中删除了g。:)
serenesat

4

您可以尝试awk

awk 'NR % 2 != 0' file

或者您只能打印包含Data inserted以下内容的行:

awk '$0 ~ /Data inserted/' file

我已经尝试了你们两个的答案,并且都在工作... :)
pmaipmui 2015年

3

另一个答案是,您可以使用vi / vim!

qdjddq

然后,如果您的文件是500行(例如),请键入

250 @ d

然后写并退出类型

:X

或者,如果出现问题而您不想保存:

:q!

说明:

q      #Start Recording
 d     #Put the recording into register 'd'
  j    #Move the cursor down
   dd  #Delete the line
     q #Stop recording


250    #Number of repeats
   @d  #Playback the recording in register 'd'.

2

这是完全不同的方式:

< file paste - - | cut -f1

假定奇数行不包含制表符。如果他们这样做,那么您将需要选择另一个分隔符,例如:

< file paste -d: - - | cut -d: -f1

1
当我初次看到这个问题时,我就想到了这一点……对sed一个巨大的文件(例如2000万行)进行速度测试会很有趣。无论如何,+ 1但实际上是为了避免引起头痛,请选择一个不太可能出现在文本文件中的分隔符,例如$'\002'...
don_crissti 2015年

@don_crissti是,将非打印字符用作分隔符是一个好主意。是的,这比sed解决方案要快得多。我使用创建了一个测试文件seq 100000000 > 100mil.txtpaste|cut解决方案在大约7.5秒内完成,而解决方案将近12秒sed。似乎是可重复的。 grep虽然最快。具有标准GNU工具的Ubuntu 14.04。
Digital Trauma 2015年

是的,paste+ cut已针对他们的工作进行了优化,因此毫无疑问,他们的组合很快就实现了……
don_crissti 2015年


0

它也解决了这个问题,尽管它有点慢:

vim -c "%normal jdd" -c "wq" file
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.