Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

get specific lines from a repeated range pattern in a text file

Wow, this sounds so complicated in the title, but I assume it is not quite so.

I have text files that have basically this layout:

Stimulus ...
...
...
...
Response
Stimulus ...
...
...
...
Response

I used sed to get everything in between and then further extracted information I needed.

sed -n -e '/Stimulus/,/Response/ p'

However, sometimes the participants do not respond, in which case the file looks like this:

Stimulus ...
...
...
...
Stimulus ...
...
...
...
Response

In this special case, my script will not get what I am looking for. So, I am looking for a way to extract the information if and only if the pattern1 is followed by pattern2, not pattern1 again.

Let me know, if I formulated it unclear. I am more then happy to provide further information.

like image 276
Andrej Avatar asked Jun 28 '13 13:06

Andrej


People also ask

How do I grep certain lines in a file?

The grep command searches through the file, looking for matches to the pattern specified. To use it type grep , then the pattern we're searching for and finally the name of the file (or files) we're searching in. The output is the three lines in the file that contain the letters 'not'.

Which command is used to extract specific lines records from a file?

The cut command offers many ways to extract portions of each line from a text file. It's similar to awk in some ways, but it has its own advantages and quirks.

How do I display a specific line in a file in Linux?

Using the head and tail Commands Let's say we want to read line X. The idea is: First, we get line 1 to X using the head command: head -n X input. Then, we pipe the result from the first step to the tail command to get the last line: head -n X input | tail -1.


1 Answers

One dirty way, although it seemed to work in my test, could be to reverse the file content, search from Response to Stimulus and reverse again the result.

Assuming following input data:

Stimulus 1...
...
...
...
Stimulus 2...
...
...
...
Response 2
Stimulus 3...
...
...
...
Response 3
Stimulus 4...
...
...
...
Stimulus 5...

The command:

tac infile | sed -ne '/Response/,/Stimulus/ p' | tac -

Yields:

Stimulus 2...
...
...
...
Response 2
Stimulus 3...
...
...
...
Response 3

EDIT: For an example with isolated Response parts. There is to filter twice (based on a comment of the OP):

tac infile | 
  sed -ne '/Response/,/Stimulus/ p' | 
  tac - | 
  sed -ne '/Stimulus/,/Response/ p'
like image 91
Birei Avatar answered Sep 21 '22 18:09

Birei