Graham P Heath
Graham P Heath

Reputation: 7399

In AWK, skip the rest of the current action?

Thanks for looking.

I have an AWK script with something like this;

/^test/{
  if ($2 == "2") {
    # What goes here?
  }

  # Do some more stuff with lines that match test, but $2 != "2".
}


NR>1 {
  print $0
}

I'd like to skip the rest of the action, but process the rest of the patterns/actions on the same line.

I've tried return but this isn't a function. I've tried next but that skips the rest of the patterns/actions for the current line.

For now I've wrapped the rest of the ^test action in the if statement's else, but I was wondering if there was a better approach.

Not sure this matters but I am using gawk on OSX, installed via brew (for better compatibility with my target OS).

Update (w/solution):

Edits: Expanded code sample based on @karakfa's answer.

BEGIN{
  keepLastLine = 1;
}
/^test/ && !keepLastLine{
  printLine = 1;
  print $0;
  next;
}

/^test/ && keepLastLine{
  printLine = 0;
  next;
}

/^foo/{
  # This is where I have the rest of my logic (approx 100 lines), 
  # including updates to printLine and keepLastLine
}

NR>1 {
  if (printLine) {
    print $0
  }
}

This will work for me, I even like it better that what I was thinking of.

However I do wonder what if my keepLastLine condition was only accessible in a for loop?

I gather from what @karakfa has said, there isn't a control structure for exiting only an action, and continuing with other patterns, so that would have to be implemented with a flag of some sort (not unlike @RavinderSingh13's answer).

Upvotes: 0

Views: 759

Answers (2)

RavinderSingh13
RavinderSingh13

Reputation: 133700

If I got it correct could you please try following. I am creating a variable named flag here which will be chedked if condition inside test block for checking if 2nd field is 2 is TRUE then it will be SET. When it is SET so rest of statements in test BLOCK will NOT be executed. Also resetting flag's value before read starts for a line too.

awk '
{
 found=""
}
/^test/{
  if ($2 == "2") {
    # What goes here?
    found=1
  }
  if(!found){
  # Do some more stuff with lines that match test, but $2 != "2".
  }
}
NR>1 {
  print $0
}'  Input_file


Testing of code here:

Let's say following is the Input_file:

cat Input_file
file
test 2 file
test
abcd

After running code following we will get following output, where if any line is having test keyword and NOT having $2==2 then also it will execute statements outside of test condition.

awk '
{
 found=""
}
/^test/{
  if ($2 == "2") {
    print "# What goes here?"
    found=1
  }
  if(!found){
   print "Do some more stuff with lines that match test, but $2 != 2"
  }
}
NR>1 {
  print $0
}'   Input_file
# What goes here?
test 2 file
Do some more stuff with lines that match test, but $2 != 2
test
abcd

Upvotes: 3

karakfa
karakfa

Reputation: 67537

the magic keyword you're looking for is else

/^test/{ if($2==2) {  } # do something
         else {  }      # do something else  
       }

NR>1                    # {print $0} is implied. 

for some reason if you don't want to use else just move up condition one up (flatten the hierarchy)

/^test/ && $2==2 {  } # do something
/^test/ && $2!=2 {  } # do something else  
# other action{statement}s           

Upvotes: 2

Related Questions