4

So parse a text file and print out line 1 and line 14, and then do nothing with lines 15-46, and then print out line 47 and line 60, etc until the end of the file. So basically every 46 lines, print out the 1st and 14th line, repeatedly for every 46 lines until EOF

0

3 Answers 3

12

Using GNU sed's first~step address range extension:

sed -n '1~46p; 14~46p;' file
11

Since you have awk in your tags, I will provide a solution with awk:

awk '(NR%46==1||NR%46==14){print}' file
2
  • 1
    Clear and concise - obviously awk is the right tool for this job :)
    – Paul Evans
    Jan 16, 2018 at 2:11
  • 3
    awk 'NR%46==1||NR%46==14' file suffices, since awk triggers a {print $0} when a true condition occurs.
    – fedorqui
    Jan 16, 2018 at 7:23
5

No job for POSIX sed:

sed 'H;1h;$!d;x;y/\n#/#\n/;s/\(#[^#]*\)\{12\}#\([^#]*\)\([^#]*#\)\{33\}/#\2##/g;s/\(.*\)##.*/\1/;s/##/#/g;y/\n#/#\n/'

Although I consider it to be nonsense using plain POSIX sed for such a task when other tools are better suited, I'll add an explanation, because there are useful elements here you may need in actual tasks:

  • H;1h;$!d;x is a pattern to collect the whole file in the pattern space, which is often useful (with GNU sed, you can replace it by using the -z option). You can figure out how it works.
  • y/\n#/#\n/ exchanges the newlines with another char (in this case #). Do this as a workaround before and after your processing if you need expressions like "every char except newline". Again, you don't need it with GNU sed, as [^\n] is allowed there.
  • That weird pattern in the s command matches 12+1+33=46 # (formerly newlines) and 45 [^#]*, which are the line contents. The every first line is untouched, 12 are removed, 1 preserved as \2 and 33 removed. This is globally done. The ## stuff is done to remove trailing lines.
6
  • 2
    An explanation of this magic incantation would be much appreciated. Jan 15, 2018 at 21:21
  • 1
    Honestly? Despite that this is clearly the wrong tool? Explaining how to hammer a nail with a screwdriver?
    – Philippos
    Jan 15, 2018 at 21:38
  • @shadowtalker Okay, I did. There are parts to learn for real-world cases.
    – Philippos
    Jan 16, 2018 at 10:12
  • With POSIX sed, you can always do sed -n 'p;n;n;n;n;n;...;n;p;n;n;n...;n' with enough ns. POSIX seds are not required to be able to store more than 10xLINE_MAX bytes in their hold or pattern space so storing the whole input there is not a good idea. Jan 16, 2018 at 11:02
  • You need a loop around all those ps and ns
    – Philippos
    Jan 16, 2018 at 11:19

Not the answer you're looking for? Browse other questions tagged .