I want to search the pattern in a certain range but in reverse order. For example if I give the range say the range I have given is 2,8 then I want that search should be performed in reverse order. I mean search should be performed from line number 8 to 2 and if any line match the pattern then print the line number

Let's say I have an input file like this..

Hello world
Hello Universe
Hello Universe
Hello Maths
Hello Physics
Hello Earth
Hello Universe
Hello Tennis
Hello God
Hello Teacher

So there are 10 lines in the file. Now I want to search the input Hello Universe between line 8 to 2. So the output should be the line numbers where we match the Hello Universe

So as per above example the output should be


I have tried this command sed -n '!G;h;2,8{\|Hello Universe|=}' a.txt but it actually perform the search in ascending order

I have searched on internet and found if we do sed '1!G;h;$!d' a.txt then it actually print the file in reverse order. Just want to modify this command such that it print the line number in reverse order on each pattern match.

So How can I modify the command. Please help

  • @terdon \|perl: warning:| is actually a string which I wanted to match in my real case. But to explain my doubt here I have taken the example of Hello Universe string. Thank you for pointing out. Corrected it
    – vivek
    May 27 '20 at 10:29

Assuming all you want is to find the matches in the lines 200 to 250 of a text file, but starting from 250 and until 200, an easy solution would be to tac the file which just prints it in reverse order. You can then use grep -n to search for your pattern and print the line number and a little perl script to change the line number to the correct one in the original file. Something like this:

sed -n '200,250p' file | tac | grep -n "$pattern" | perl -pe 's/(^\d+)/251-$1/e'

If we create a test file with:

printf 'Line number %d\n' {1..400} > file

And then use 21 as the pattern, we should get back lines 210 to 219, and 221:

$ sed -n '200,250p' file | tac | grep -n 21 | perl -pe 's/(^\d+)/251-$1/e'
221:Line number 221
219:Line number 219
218:Line number 218
217:Line number 217
216:Line number 216
215:Line number 215
214:Line number 214
213:Line number 213
212:Line number 212
211:Line number 211
210:Line number 210
  • Thanks for the answer. Your answer meets my requirement but just wondering if it possible only with sed I mean without using tac. Please provide your thought on this
    – vivek
    May 26 '20 at 18:19
  • I would guess it is indeed possible, @vivek, sed is very powerful, but I have no idea how. Add an example file and output to your question and maybe someone with better sed knowledge can answer.
    – terdon
    May 26 '20 at 23:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.