The problem I am working through is that I have a file that will contain fields delimited by a "|" and the file is sorted based on one of those fields. What I have been trying to come up with is a way to grab lines based on a range of a certain field.

an example:

Sample input would be something like this where it is sorted based on the 2nd field. So they are listed in alphabetical order


The range I want to get would then be "we want all records that fall in the range of abcd - abcf to be recorded into a different file. And the records remaining would be:


When I started I think I approached this in the wrong way. I was looping through each line and then trying to check the line against a regular expression to see if I wanted the line or not. But would there be a better way of doing this using awk and grep?

5 Answers 5


all records that fall in the range of abcd - abcf

Simple awk solution:

awk -F'|' '$2~/^abc[d-f]$/' file

The output:


Another solution :

awk -F'|' '{if ($2 == "abcd") { l=1} else if ($2 == "abcg") { l=0} }l' file 

A sed solution.

To delete the lines before the first in the range:

cat file | sed '/abcd/Q'

To delete the lines after the last in range:

cat file | sed -n '/abcf/,$p'

   -n : don't print non-matches
   ,$ : first match to end of file
   p  : print

Putting together:

cat file | sed '/abcd/Q | sed -n '/abcf/,$p'

The patterns will match any field in the line, so you would need a better pattern to match only the second field:

cat file | sed -r -n '/^[^\|]+\|abcd/,$p' | sed -r '/^[^\|]+\|abce/Q'

The very simple range using sed would be:

cat file | sed -n '/abc[def]/p'

records in the range of abcd - abcf using grep:

grep -E '^[^\|]+\|abc[d-f]\|'

All-in-one sed solution, writing the range from abcd to abcf to a file called other, while remaining lines are passed to stdout. So you don't have to go through the file twice.

sed -e '/|abcd|/,/|abcf|/{wother' -e 'd;}'

You must log in to answer this question.

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