1

I have an input like:

1
2
3
4
5
6
7
8

And I'd like to retrieve only N first and M last lines from this input.

For example, if N is 2 and M is 4 I want the result to be:

1
2
5
6
7
8

Lines can overlap, so if N is 6 and M is 4 I want the output to be equal to my input.

I have tried using awk, with no luck:

cat input | awk "{if (NR<2 || NR>count - 4) {print}}"
Jezor
  • 113
  • 5

2 Answers2

2

Like this:

awk 'NR <= 2 || lines - 4 < NR {print}' lines=(wc -l input) input

Since awk cannot possibly know number of lines in a file before it reaches end of file, you need to input the number of lines as a variable to awk.

jijinp
  • 368
  • 2
  • 5
1

Here's one technique:

$ seq 10 > input
$ set N 2; set M 4
$ set wanted (sed $N'q' input; tac input | sed $M'q' | tac)
$ printf "%s\n" $wanted
1
2
7
8
9
10

If N+M > num_lines then you will get duplicate lines with this approach.

Or, use fish's array subscripting:

$ set lines (cat input)
$ printf "%s\n" $lines[1..$N] $lines[(math (count $lines) - $M + 1)..-1]
1
2
7
8
9
10
glenn jackman
  • 4,320
  • 16
  • 19
  • The second approach produces `(standard_in) 1: syntax error`. I am looking for a one-liner: `set lines (cat /tmp/test); printf "%s\n" $lines[1..$N] $lines[(math (count $lines) - $M + 1)..-1]` – Jezor May 11 '17 at 10:27
  • You need to set the `N` and `M` variables to resolve the syntax errors: `set N 2; set M 4; set lines ...` – glenn jackman May 11 '17 at 19:11