Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unix command to get lines from in between first and last occurence of a word and write to a file

I want a unix command to find the lines between first & last occurence of a word

For example:

let's imagine we have 1000 lines. Tenth line contains word "stackoverflow", thirty fifth line also contains word "stackoverflow".

I want to print lines between 10 and 35 and write it to a new file.

like image 479
Krishna Avatar asked Oct 21 '13 13:10

Krishna


People also ask

How to view first 10 lines of a file in Linux?

You can use any one of the following command on Unix or Linux to view first 10 lines of a file: head command sed command awk command Perl/Python/Php/Ruby

How to print specific lines from a file in Linux?

Printing specific lines from a file is no exception. To display 13th line, you can use a combination of head and tail: Or, you can use sed command: To display line numbers from 20 to 25, you can combine head and tail commands like this: Or, you can use the sed command like this: Detailed explanation of each command follows next.

How to print the first 20 lines of a group in Linux?

Type the following sed command to display first 10 lines of a file named “/etc/group”: sed-n 1,10p / etc / group. Type the following sed command to display first 20 lines of a file named “/etc/group”: sed-n 1,20p / etc / group. awk command example to print first 10/20 lines.

How to print the first 20 lines of a file using SED?

Type the following sed command to display first 10 lines of a file named “/etc/group”: sed-n 1,10p / etc / group. Type the following sed command to display first 20 lines of a file named “/etc/group”: sed-n 1,20p / etc / group. awk command example to print first 10/20 lines.


2 Answers

You can make it in two steps. The basic idea is to:

1) get the line number of the first and last match.

2) print the range of lines in between these range.

$ read first last <<< $(grep -n stackoverflow your_file | awk -F: 'NR==1 {printf "%d ", $1}; END{print $1}')
$ awk -v f=$first -v l=$last 'NR>=f && NR<=l' your_file

Explanation

  • read first last reads two values and stores them in $first and $last.
  • grep -n stackoverflow your_file greps and shows the output like this: number_of_line:output
  • awk -F: 'NR==1 {printf "%d ", $1}; END{print $1}') prints the number of line of the first and last match of stackoverflow in the file.

And

  • awk -v f=$first -v l=$last 'NR>=f && NR<=l' your_file prints all lines from $first line number till $last line number.

Test

$ cat a
here we
have some text
stackoverflow

and other things
bla
bla
bla bla
stackoverflow
and whatever else
stackoverflow
to make more fun
blablabla

$ read first last <<< $(grep -n stackoverflow a | awk -F: 'NR==1 {printf "%d ", $1}; END{print $1}')
$ awk -v f=$first -v l=$last 'NR>=f && NR<=l' a
stackoverflow

and other things
bla
bla
bla bla
stackoverflow
and whatever else
stackoverflow

By steps:

$ grep -n stackoverflow a
3:stackoverflow
9:stackoverflow
11:stackoverflow

$ grep -n stackoverflow a | awk -F: 'NR==1 {printf "%d ", $1}; END{print $1}'
3 11

$ read first last <<< $(grep -n stackoverflow a | awk -F: 'NR==1 {printf "%d ", $1}; END{print $1}')

$ echo "first=$first, last=$last"
first=3, last=11
like image 167
fedorqui 'SO stop harming' Avatar answered Sep 22 '22 20:09

fedorqui 'SO stop harming'


If you know an upper bound of how many lines there can be (say, a million), then you can use this simple abusive script:

(grep -A 100000 stackoverflow | grep -B 1000000 stackoverflow) < file

You can append | tail -n +2 | head -n -1 to strip the border lines as well:

(grep -A 100000 stackoverflow | grep -B 1000000 stackoverflow
  | tail -n +2 | head -n -1) < file
like image 41
Alfe Avatar answered Sep 23 '22 20:09

Alfe