tags:

views:

425

answers:

6

Hi! I have a file

line a - this is line a
line b - this is line b
line c - this is line c
line d - this is line d
line e - this is line e

The question is: How can I output the lines starting from "line b" till "line d" using bash commands? I mean, to obtain:

"line b - this is line b
 line c - this is line c
 line d - this is line d"
+2  A: 

If by bash, you mean actually bash alone, I can't help you. You really should be using the right tools for the job. If you mean standard UNIX utilities that you can call from bash, I would be using awk for that.

echo 'line a - this is line a
line b - this is line b
line c - this is line c
line d - this is line d
line e - this is line e' | awk '
    BEGIN {e=0}
    /^line b/ {e=1}
    /^line d/ {if (e==1) {print;exit}}
    {if (e==1) print}
'

This outputs:

line b - this is line b
line c - this is line c
line d - this is line d

The way it works is simple.

  • e is the echo flag, initially set to false (0).
  • when you find line b, set echo to true (1) - don't print yet. That will be handled by the last bullet point below.
  • when you find line d and echo is on, print it and exit.
  • when echo is on, print the line (this includes line b).

I've made an assumption here that you don't want to exit on a line d unless you're already echoing. If that's wrong, move the exit outside of the if statement for line d:

    /^line d/ {if (e==1) print;exit}

Then, if you get a line d before your line b, it will just exit without echoing anything.

The "/^line X/"-type clauses can be made very powerful to match pretty well anything you can throw at it.

paxdiablo
Mm. Think I read the question wrong.
Paolo Bergantino
+1  A: 

Your example is not enough to infer what you want in the general case, but assuming you want to remove the first and last line, you can simply use

tail -n+2 $filename | head -n-1

Here tail -n+2 prints all the lines starting from the second, and head -n-1 prints all the lines except the last.

Paolo Capriotti
+1  A: 

You can do it using bash alone, though I agree with Pax that using other tools is probably a better solution. Here's a bash-only solution:

while read line
do
    t=${line#line b}
    if test "$t" != "$line"
    then
     echo $line
     while read line
     do
      echo $line
      t=${line#line d}
      if test "$t" != "$line"
      then
       exit 0
      fi
     done
    fi
done
anon
+3  A: 

for your set of sample data:

awk '/line b/,/line d/' file

Or

awk '/line d/{f=0;print}/line b/{f=1}f' file
ghostdog74
A: 

Another approach which depends on what you mean:

pcregrep -m 'line b - this is line b
 line c - this is line c
 line d - this is line d' file
notnoop
A: 
sed -n '/line b/,/line d/p' file