ajr_chm
ajr_chm

Reputation: 65

Awk "else" condition prints string on every line matching condition. How to limit print of string to one time only

I am processing a file with the following awk script. The script is producing an output that prints "There are no 7 day repeats" for every line in the original data file. See below for the script, data file, current result and desired result(s).

#! /usr/bin/awk -f

BEGIN { 
    FS = "|"; ORS = "\n\n" 
    print "7 day repeats"
}
NR == 1 
          

NR==2 || NR==3   

{   if ($5 ~ 7)   
        print $0

        else 

    print  "There are no 7 day repeats"
    
}   

Data file

Date: 
15-02-2023

Name          | formula     | no.  | dose | days | cost  | msg | em | notes | consult | WYLQ
Customer Name | XJZT+LGZGT  | 9131 | 3⅔   | 14   | 54.80 | x   | 1  | Ca    | ph      | d-c
Customer Name | trauma-UT   | 9132 | 5¾   | 10   | 66.30 | x   | 2  | Ca    | ph      | --
Customer Name | LGZGT+CM,GG | 9133 | 1    | 14   | 21.25 | x   | 1  | IB    | F       | d-c
Customer Name | LGCZT       | 9134 | 2½   | 14   | 46.15 | x   | 2  | IB    | ph      | d-c

Current result

7 day repeats

Date: 

There are no 7 day repeats

15-02-2023

There are no 7 day repeats

Name          | formula     | no.  | dose | days | cost  | msg | em | notes | consult | WYLQ

There are no 7 day repeats

There are no 7 day repeats

There are no 7 day repeats

There are no 7 day repeats

There are no 7 day repeats

Desired result

7 day repeats

Date: 

15-02-2023

There are no 7 day repeats

If ($5 ~ 7) I would like the out put to look like this

Date: 

15-02-2023

Name          | formula     | no.  | dose | days | cost  | msg | em | notes | consult | WYLQ

Customer Name | XJZT+LGZGT  | 9131 | 3⅔   | 7    | 54.80 | x   | 1  | Ca    | ph      | d-c

I tried placing placing an exit after the print "There are no 7 day repeats"

producing the following result

7 day repeats

Date: 

There are no 7 day repeat

I can see that my print statement after the else is probably to effectively asking awk to print "There are no 7 day repeats" on every line where $5 !~ 7 . But I am at a loss as to how to stop this behaviour. I can get my last desired result (should $5 ~ 7) by removing everything after print $0 but I would like by script to at least do two jobs at one time should that be possible.

Upvotes: 1

Views: 72

Answers (2)

markp-fuso
markp-fuso

Reputation: 34244

Assumptions:

  • 7 day repeats should show at the top of all outputs
  • OP wants $5 ~ 7 to match on anything with a literal 7 in the field (eg, 7, 17, -27, 374)
  • the table header record (Name | formula | ...) should only be printed if we find at least one line where $5 ~ 7
  • we should print all lines where $5 ~ 7

Sample data files:

$ head file1 file2
==> file1 <==
Date:
15-02-2023

Name          | formula     | no.  | dose | days | cost  | msg | em | notes | consult | WYLQ
Customer Name | XJZT+LGZGT  | 9131 | 3⅔   | 14   | 54.80 | x   | 1  | Ca    | ph      | d-c
Customer Name | trauma-UT   | 9132 | 5¾   | 10   | 66.30 | x   | 2  | Ca    | ph      | --
Customer Name | LGZGT+CM,GG | 9133 | 1    | 14   | 21.25 | x   | 1  | IB    | F       | d-c
Customer Name | LGCZT       | 9134 | 2½   | 14   | 46.15 | x   | 2  | IB    | ph      | d-c

==> file2 <==
Date:
15-02-2023

Name          | formula     | no.  | dose | days | cost  | msg | em | notes | consult | WYLQ
Customer Name | XJZT+LGZGT  | 9131 | 3⅔   | 14   | 54.80 | x   | 1  | Ca    | ph      | d-c
Customer Name | trauma-UT   | 9132 | 5¾   |  7   | 66.30 | x   | 2  | Ca    | ph      | --
Customer Name | LGZGT+CM,GG | 9133 | 1    | 14   | 21.25 | x   | 1  | IB    | F       | d-c
Customer Name | LGCZT       | 9134 | 2½   | 27   | 46.15 | x   | 2  | IB    | ph      | d-c

One awk idea:

awk '
BEGIN          { FS = "|"; ORS = "\n\n"
                 print "7 day repeats"
               }
NR <= 2                                           # print 1st 2 lines of input
$2 ~ /formula/ { hdr=$0 }                         # save the table header record
$5 ~ 7         { if (hdr) {                       # if hdr is non-blank then ...
                    print hdr                     # print hdr and ...
                    hdr=""                        # set hdr to blank (so it will not be printed again)
                 }
                 print $0                         # print table record where "$5 ~ 7"
                 found=1                          # set a flag indicating we found a match
               }
END            { if (! found)                     # if no match ($5 ~ 7) found then ...
                    print  "There are no 7 day repeats"
               }
' filename

For file1 this generates:

7 day repeats

Date:

15-02-2023

There are no 7 day repeats

For file2 this generates:

7 day repeats

Date:

15-02-2023

Name          | formula     | no.  | dose | days | cost  | msg | em | notes | consult | WYLQ

Customer Name | trauma-UT   | 9132 | 5¾   |  7   | 66.30 | x   | 2  | Ca    | ph      | --

Customer Name | LGCZT       | 9134 | 2½   | 27   | 46.15 | x   | 2  | IB    | ph      | d-c

Upvotes: 0

dash-o
dash-o

Reputation: 14452

Seems like OP would like to

  • Include header "7 days repeat"
  • copy first 4 lines of the input
  • Print every remaining line (lines 5 ... ) when columns 5 (days) has value of 7
  • Show tailing message "there are no ..." if no line matches

To achieve this, few changes to logic for lines >4: the condition for lines 1..4 modified to 'print ; next', condition for lines 5+ changes to check for numeric 7 (instead of ~ 7, which will also match 17, 72, ..., and a footer section was added, with condition printout.

#! /usr/bin/awk -f

# Header
BEGIN {
    FS = "|"; ORS = "\n\n"
    print "7 day repeats"
}
# Lines 1..4
NR <= 4 { print ; next }
# Lines 5 ...
+$5 == 7 { n_match++ ; print }
# Footer
END {
    if (!n_match) print  "There are no 7 day repeats"
}

Upvotes: 1

Related Questions