4

I have one requirement. Let’s say my file contents are

a
b
c
d
e
f
d
e
f

I want to print the lines from b to 2nd time repeated d. Is there any command using awk to do this?

Output should be

b
c
d
e
f
d

If it is first time b, I know the command

awk '/b/,/d/' file.txt

But I want to print the text to the matching point if it repeats second time. I want to have the command with in one line.

2 Answers 2

7

One way is to use flags and counter to keep track

$ awk '/b/{f=1; c=0} f; /d/ && ++c==2{f=0}' file.txt
b
c
d
e
f
d
  • /b/{f=1; c=0} set flag for starting match and initialize counter
  • f; print input record as long flag is set
  • /d/ && ++c==2{f=0} clear the flag if ending string is matched for second time
  • can simplify to awk '/b/{f=1} f; /d/ && ++c==2{exit}' if there is only one set to be extracted


Note that if ending match doesn't have 2 matches, it will print until end of input

$ seq 10 | awk '/4/{f=1; c=0} f; /6/ && ++c==2{f=0}'
4
5
6
7
8
9
10
2
  • 1
    You could also let f double as the counter, e.g.: /b/ { f=2 } f; /d/ { f-- }
    – Thor
    Commented Nov 13, 2017 at 9:04
  • @Thor good idea, but need /d/ && f{ f-- } as negative numbers evaluate as true
    – Sundeep
    Commented Nov 13, 2017 at 9:14
1
  1. A more readable code. Keep track of the counts of characters.
  2. Print as long as count of b=1 and d<=2.
  3. Stop once count of d has reached 2.

    awk '{ a[$1]++;
        if(a["b"]==1 && a["d"]<=2){
            print;
        }
        if(a["d"]==2){
           a["d"]=10
        }
    }' file.txt
    

You must log in to answer this question.

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