24

File:

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

Expected output file:

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

I want the output to look this way: every second line will be deleted but there will be no gap between lines.

  • 5
    Do you want to delete every second line or all lines that contains "No error occurred"? What if two consecutive lines had "No error occurred"? – Tulains Córdova Aug 4 '15 at 16:42
  • 1
    @user1598390 I think... in that case grep -v "No error occurred" file this command should work... what @paul has answered. In the output file, there will be no lines containing "No error occurred" this part. – pmaipmui Aug 6 '15 at 16:38
  • 1
    Then the title of the question is misleading. – Tulains Córdova Aug 6 '15 at 20:17
35
+50

With sed:

sed -e n\;d <file

With POSIX awk:

awk 'FNR%2' <file

If you have older awk (like oawk), you need:

oawk 'NR%2 == 1' <file

With ex:

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

will edit the file in-place.

  • g mark a global command
  • /$/ match every lines
  • +d delete the next line
  • wq! save all changes

This approach share the same ideal with sed approach, delete every next line of current line start from line 1.

With perl:

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

and perl6:

perl6 -ne '.say if $*IN.ins % 2' <file
perl6 -ne '.say if ++$ % 2' <file
  • Yes... its working ... :) ... first one is working.... i have also tried the second one.. its telling `awk : syntax error line1 awk: bailing out near line 1' – pmaipmui Aug 3 '15 at 10:03
  • sed -e n\;d <file ~ Yes its working @cuonglm... – pmaipmui Aug 3 '15 at 10:10
  • 1
    I'm guessing that you used n\;d instead of 'n;d' to save a precious character but that logic goes out of the window when you're unnecessarily using the -e switch and a file redirection <! – Tom Fenech Aug 4 '15 at 11:50
  • 1
    @Geek: It's just a shorter version of sed -e 'n;d', save you one character. – cuonglm Sep 30 '15 at 6:21
  • 1
    @Geek: n command write pattern space to standard output if -n was used, then replace pattern space with next line. Here's every odd line will be printed by n, even line then read into pattern space but delete immediately by d command`. – cuonglm Sep 30 '15 at 6:37
62

Solving this by deleting every second line can be error prone (for example, when process sometimes generates two meaningful lines instead one). May be it is better to filter out the garbage:

grep -v "No error occurred" file

It can run as filter, you can add more garbage patterns here and improve the result.

  • 9
    +1 for pointing out that sometimes the second line is important! – Kaz Wolfe Aug 4 '15 at 3:45
12

Ассоrding to the question, with GNU sed:

sed '0~2d' file

will delete every second line but I'd like to offer filter lines by it content:

sed '/Data/! d' file

or with same result

sed '/No error/d' file
  • sed '/No error/d' file ~ gives the desired output @Costas – pmaipmui Aug 3 '15 at 10:08
  • 5
    Note that the last two are convoluted ways to write grep Data and grep -v 'No error' – Stéphane Chazelas Aug 4 '15 at 9:14
5

Here is a way using sed:

sed -n 'p;n' filename

Another way with GNU sed:

sed -n '1~2p' filename

Output from above commands:

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
  • What do you mean when saying shortest way using sed? – cuonglm Aug 3 '15 at 12:08
  • What is the reason in g command? sed -n 'p;n' is enough. – Costas Aug 3 '15 at 12:14
  • @cuonglm: I mean to say simple way of doing. By the way removed that word. :) – serenesat Aug 3 '15 at 12:22
  • @Costas: Thanks! Just checked, its working without g. removed g from command. :) – serenesat Aug 3 '15 at 12:24
4

You can try with awk:

awk 'NR % 2 != 0' file

or you can print only lines containing Data inserted:

awk '$0 ~ /Data inserted/' file
  • I have tried both of you answers and both are working... :) – pmaipmui Aug 3 '15 at 10:05
3

Another answer, you could use vi/vim!

qdjddq

And then if your file was 500 lines (for example) type

250@d

And then to write and exit type

:x

Or if something goes wrong and you don't want to save:

:q!

Explanation:

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

Here's quite a different way of doing it:

< file paste - - | cut -f1

This assumes that the odd-numbered lines do not contain tabs. If they do, then you'll need to pick another separator character, e.g. : here:

< file paste -d: - - | cut -d: -f1
  • 1
    I had this in mind when I first saw the question... It'd be interesting to run a speed test against sed with a huge file (e.g. 20 mil lines). Anyways, +1 but really, to avoid headaches, pick a delimiter that's unlikely to occur in a text file, like $'\002'... – don_crissti Aug 7 '15 at 0:29
  • @don_crissti yes use of a non-printing character for the separator is a good idea. And yes, this is measurably faster than the sed solution. I created a test file with seq 100000000 > 100mil.txt. The paste|cut solution finished in about 7.5 seconds, vs nearly 12 for the sed solution. Seems to be repeatable. grep is fastest though. Ubuntu 14.04 with standard GNU tools. – Digital Trauma Aug 7 '15 at 0:40
  • Yep, paste + cut are heavily optimized for their job so unsurprisingly their combination is pretty damn fast... – don_crissti Aug 7 '15 at 0:45
1

Another option (shorter)

sed 'n; d' file
  • 3
    It's longer than mine sed n\;d, adding -e is only my habit. – cuonglm Aug 3 '15 at 13:05
0

It also solves the problem, though it is a bit slower:

vim -c "%normal jdd" -c "wq" file

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.