Skip to content
VLSI Mentor

awk Part II · Module 5 · Variables, Operators, and Control Flow

if and else

Chapters 5.1 and 5.3 kept reaching for if before it had been introduced — to seed a tracker, to guard a divisor, to reject a malformed measurement. This chapter covers it properly: the branch forms, the chain, the boundary condition that decides whether a score of exactly 80 passes, and the missing pair of braces that changes which statements are conditional while leaving the printed lines identical. Then the finding that makes this the most important chapter in the module to get right — a test with no recorded score, classified by a perfectly ordinary comparison as PASS.

Foundation18 min readawkPart IIControl FlowConditionalsData Quality

Part II · Module 5 · Chapter 5.4 · if and else

1. Why This Matters

Module 4 taught you to select records with patterns. A pattern decides whether an action runs. What it cannot do is choose which of two actions runs.

That is what if is for, and the difference is the subject of section 10. Everything that classifies rather than filters needs it: PASS or FAIL, within budget or over, analysed or skipped, usable measurement or not.

The chapter has two hazards worth the price of admission. One is a pair of braces whose absence changes a count from 2 to 4 while the printed output stays identical. The other is section 9, where an ordinary comparison against an ordinary report column reports a test that was never scored as having passed — and where the direction of the error turns out to depend on which character the tool vendor chose to mean "no data".

2. The Simplest Form

if (condition) statement runs the statement when the condition is true:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk 'BEGIN { s = 95; if (s >= 80) print "PASS" }'
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
PASS

The parentheses around the condition are required — unlike in some languages, awk will not accept if s >= 80.

If the condition is false, nothing happens and there is no output. Chapter 5.1's rule about truth applies here in full: zero and the empty string are false, everything else is true, and a field containing 0 is false while the string "0" is true.

3. if and else

else supplies the alternative:

Azvya Education Pvt. Ltd.VLSI Mentor
scores.txt — synthetic teaching data. A test name and a coverage score.
alu 95
fifo 72
uart 88
spi 45
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 >= 80) print $1, "PASS"; else print $1, "FAIL" }' scores.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu PASS
fifo FAIL
uart PASS
spi FAIL

Every record produces exactly one line, because the two branches are mutually exclusive and together cover every case.

Note the semicolon before else. awk needs a statement terminator there; print $1, "PASS" else … is a syntax error. This is the single most common typo in awk conditionals.

A branch. On the left, the current record arrives. In the middle, the condition dollar-two greater than or equal to eighty is evaluated. On the right, two mutually exclusive outcomes: the upper box, reached by the edge labelled true, prints PASS; the lower box, reached by the edge labelled false, prints FAIL. Exactly one of the two is reached for each record.Current recordone line, fields splitif ($2 >= 80)evaluated onceprint PASSthe true branchprint FAILthe else branchtruefalse12
Figure 1 — one record, one condition, two mutually exclusive outcomes. The condition is evaluated once per record and exactly one branch runs, which is why the output in section 3 has four lines for four records rather than eight or two. The true path and the false path are shown as mirror images deliberately: nothing about the structure favours one over the other, and a record that takes neither is impossible.

4. The else if Chain

More than two categories means chaining. else if is not special syntax — it is an if that happens to be the statement belonging to an else:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 >= 90) print $1, "A"; else if ($2 >= 80) print $1, "B"; else if ($2 >= 70) print $1, "C"; else print $1, "F" }' scores.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu A
fifo C
uart B
spi F

95 → A, 72 → C, 88 → B, 45 → F.

The chain is tested top to bottom and stops at the first match, which is why the order of the thresholds matters and why they are written descending. Reverse them and everything collapses into the first branch:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 >= 70) print $1, "C"; else if ($2 >= 80) print $1, "B"; else if ($2 >= 90) print $1, "A"; else print $1, "F" }' scores.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu C
fifo C
uart C
spi F

Three Cs. alu scored 95, which is >= 70, so the first branch claimed it and the >= 90 test was never reached. The A and B branches are now dead code — unreachable for any input.

That is a genuine class of bug rather than a curiosity. It produces plausible output, every record is still classified, and nothing warns you that two of your four categories can never occur. The check is mechanical: in a descending chain each threshold must be strictly higher than the one below it.

5. Braces: What Is Actually Conditional

This is the bug most worth internalising, because the symptom is a wrong number rather than a wrong line.

Count the passing tests while printing their names:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 >= 80) print $1; count++ } END { print "count =", count+0 }' scores.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu
uart
count = 4

Two names printed, and a count of 4. Four records, so count counted all of them.

With braces:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 >= 80) { print $1; count++ } } END { print "count =", count+0 }' scores.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu
uart
count = 2

Same two names. Count of 2, which is the answer that was wanted.

Without braces, if governs exactly one statement — the print. The count++ after the semicolon is simply the next statement in the action, run unconditionally for every record. awk is doing precisely what was written.

Indentation does not affect this. awk ignores whitespace entirely, so a count++ indented to look like it belongs to the if still runs unconditionally. Only braces group statements.

6. The Boundary

A threshold comparison has to decide what happens at exactly the threshold, and this is where specifications are usually silent.

Azvya Education Pvt. Ltd.VLSI Mentor
boundary.txt — synthetic. Two tests, both scoring exactly the threshold value.
alu 80
fifo 80
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 > 80) print $1, "gt80-PASS"; else print $1, "gt80-fail" }' boundary.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu gt80-fail
fifo gt80-fail
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 >= 80) print $1, "ge80-PASS"; else print $1, "ge80-fail" }' boundary.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu ge80-PASS
fifo ge80-PASS

A score of exactly 80 fails a > 80 test and passes a >= 80 test. Both commands are correct awk; they implement different policies.

This matters because "80% coverage required" is ambiguous in English and unambiguous in code. If the sign-off criterion is 80% and a block achieves exactly 80.0%, the two commands above disagree about whether it ships.

The engineering habit: write the boundary into the output so the policy is auditable.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 >= 80) print $1, $2, "PASS (>= 80)"; else print $1, $2, "FAIL (< 80)" }' boundary.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu 80 PASS (>= 80)
fifo 80 PASS (>= 80)

Now a reader can see which rule produced the verdict without reading the script. On a real sign-off report that is the difference between a number somebody can check and a number they have to trust.

A related trap worth naming: a coverage figure of 79.95% rounds to 80.0% for display and fails a >= 80 test. If the displayed value and the compared value go through different formatting, the report will appear to contradict itself. Compare the raw value and display the raw value, or round both.

7. Conditions Are Expressions

Anything that evaluates to a value can be a condition. The comparison operators from Chapter 4.2 are the common case:

Azvya Education Pvt. Ltd.VLSI Mentor
kinds.txt — synthetic. An instance name and a logic kind.
u_a comb
u_b seq
u_c comb
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 == "comb") c++; else s++ } END { print c+0, s+0 }' kinds.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
2 1

Two combinational, one sequential.

The logical operators from Chapter 4.3 compose conditions:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 >= 80 && $2 < 90) print $1, "borderline" }' scores.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
uart borderline

And a regex match is a condition, from Chapter 4.4:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($1 ~ /^u_/) print $1, "has the instance prefix" }' kinds.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
u_a has the instance prefix
u_b has the instance prefix
u_c has the instance prefix

A bare value is also a condition, and this is where Chapter 5.1's truth rule earns its place:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if (NF) print NR, "has", NF, "fields"; else print NR, "is blank" }' kinds.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
1 has 2 fields
2 has 2 fields
3 has 2 fields

if (NF) reads as "if this record has any fields", because 0 is false. It is idiomatic and compact. Note that it is safe here precisely because NF is a count awk computed — Chapter 5.1's Exercise 6 showed that a bare if (v) on a field asks a different question than you probably mean.

8. The Conditional Expression

condition ? a : b is an expression that yields one of two values. It is not a statement and cannot replace if, but it is cleaner when the branches differ only in a value:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ print $1, ($2 >= 80 ? "PASS" : "FAIL") }' scores.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu PASS
fifo FAIL
uart PASS
spi FAIL

Identical output to section 3, one print instead of two.

The parentheses around it are not required by the grammar but are worth writing, because ?: has very loose precedence — looser than concatenation — and an unparenthesised ternary inside a print list is easy to misread.

Use if/else when the two branches do different things. Use ?: when they supply different values to the same action. Chapter 5.1's final exercise used it for exactly that.

9. When a Condition Meets a Malformed Field

Now the finding this chapter exists for.

Chapter 5.3 showed that a malformed measurement corrupts a mean while leaving the sum intact. A comparison fails differently, and worse.

The same scores file with one unusable value — a test that was never scored:

Azvya Education Pvt. Ltd.VLSI Mentor
scores_bad.txt — synthetic. One test has no recorded score.
alu 95
fifo n/a
uart 88

The classification from section 3, unchanged:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 >= 80) print $1, "PASS"; else print $1, "FAIL" }' scores_bad.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu PASS
fifo PASS
uart PASS

fifo passed. A test with no score at all is reported as having passed — not failed, not flagged, not skipped. It is in the PASS list, indistinguishable from alu and uart, which genuinely passed.

The mechanism is Chapter 4.2's comparison rule. $2 holds n/a, which is not a numeric string, so awk cannot compare numerically and compares as text instead. Text comparison is character by character:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk 'BEGIN { print ("n/a" >= "80") ? "\"n/a\" >= \"80\" is TRUE" : "FALSE" }'
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
"n/a" >= "80" is TRUE

n is character code 0x6e. 8 is 0x38. So "n/a" sorts after "80", the comparison is true, and the branch prints PASS.

And here is the part that removes any defence of this behaviour. Change only the placeholder's spelling:

Azvya Education Pvt. Ltd.VLSI Mentor
scores_dash.txt — synthetic. The same missing score, written as a dash.
alu 95
fifo -
uart 88
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 >= 80) print $1, "PASS"; else print $1, "FAIL" }' scores_dash.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu PASS
fifo FAIL
uart PASS

Now fifo fails. Same bug, same data, same command, opposite verdict — because - is 0x2d, which sorts before 8.

The repair is to validate the field's shape before comparing it, using Chapter 5.3's positive guard, and to give unusable data a category of its own:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 !~ /^-?[0-9]+(\.[0-9]+)?$/) print $1, "NO_SCORE"; else if ($2 >= 80) print $1, "PASS"; else print $1, "FAIL" }' scores_bad.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu PASS
fifo NO_SCORE
uart PASS

Three categories, each record in the right one, and fifo is now visibly something that needs attention rather than something that passed.

The guard has to come first in the chain. Put it last and the >= 80 test gets to the malformed field before the validation does, which is the original bug with extra code around it.

It is worth confirming the classifier separately from the verdict, because a guard that silently over-rejects is as bad as one that under-rejects:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ print $1, "[" $2 "]", ($2 ~ /^-?[0-9]+(\.[0-9]+)?$/ ? "numeric" : "NOT numeric") }' scores_bad.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu [95] numeric
fifo [n/a] NOT numeric
uart [88] numeric

Exactly one record rejected, and it is the right one.

Adding a count makes the report self-auditing:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '$2 !~ /^-?[0-9]+(\.[0-9]+)?$/ { nodata++; next } $2 >= 80 { pass++; next } { fail++ } END { printf "%d pass, %d fail, %d unscored, of %d tests\n", pass+0, fail+0, nodata+0, NR }' scores_bad.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
2 pass, 0 fail, 1 unscored, of 3 tests

The three categories sum to the record count, which is the arithmetic check that no record was silently dropped. next is Chapter 5.6's subject; here it is what keeps the three rules mutually exclusive.

10. Pattern or if?

The question you have been carrying since Module 4. These two produce the same output:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '$2 >= 80 { print $1, "PASS" }' scores.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu PASS
uart PASS
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 >= 80) print $1, "PASS" }' scores.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu PASS
uart PASS

With only a true branch, the pattern form is shorter and more idiomatic — it is the awk way to say "for records like this, do that".

The distinction is what each one controls:

Decides
patternwhether the action runs at all
ifwhich statement runs, inside an action that is already running

So the moment you need an else, you need if — a pattern has no else:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 >= 80) print $1, "PASS"; else print $1, "FAIL" }' scores.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu PASS
fifo FAIL
uart PASS
spi FAIL

You can fake it with two patterns, and it is worth seeing why you should not:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '$2 >= 80 { print $1, "PASS" } $2 < 80 { print $1, "FAIL" }' scores.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu PASS
fifo FAIL
uart PASS
spi FAIL

Identical output, and the conditions are now stated twice in a form that must stay each other's exact complement. Change the threshold in one and not the other and records fall into both categories or neither — with no error, because Chapter 2.3 established that every rule gets tested against every record.

The guidance: one condition with two outcomes is an if/else. Several independent conditions are patterns. Section 9's final command is the exception that proves the rule — its three patterns end in next, which is what makes them mutually exclusive by construction rather than by careful maintenance.

11. Nesting and Readability

if statements nest, and nesting past two levels is usually a sign the logic wants restructuring:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 ~ /^[0-9]+$/) { if ($2 >= 80) print $1, "PASS"; else print $1, "FAIL" } else print $1, "NO_SCORE" }' scores_bad.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu PASS
fifo NO_SCORE
uart PASS

Correct, and harder to read than section 9's flat chain producing the same answer. The flat version tests the exceptional case first and gets it out of the way:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 !~ /^[0-9]+$/) print $1, "NO_SCORE"; else if ($2 >= 80) print $1, "PASS"; else print $1, "FAIL" }' scores_bad.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu PASS
fifo NO_SCORE
uart PASS

Same three categories, one level of nesting, and the guard is visibly the first thing that happens. Handle the unusable case first, then branch on the value — it flattens the structure and makes the validation impossible to overlook.

12. Common Mistakes

Omitting the parentheses. if s >= 80 is a syntax error; the parentheses are required.

Omitting the semicolon before else. Also a syntax error, and the most common awk typo.

Omitting braces on a multi-statement branch. Section 5. The extra statement runs unconditionally, the printed lines look right, and a count is wrong.

Trusting indentation. awk ignores it. Only braces group.

Ordering a chain ascending. Section 4. The loosest threshold claims everything and the later branches become dead code.

Leaving the boundary implicit. > 80 and >= 80 disagree about exactly 80. Write the rule into the output.

Comparing a field that might be malformed. Section 9. n/a is reported as PASS and - as FAIL, from the same bug.

Using a bare if (v) on a field whose zero is meaningful. Chapter 5.1, Exercise 6.

Faking else with two complementary patterns. They must stay exact complements forever, and nothing checks that they do.

Nesting three levels deep. Test the exceptional case first and flatten.

13. Exercises

Exercise 1 — Predict the output

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk 'BEGIN { x = 0; if (x) print "truthy"; else print "falsy" }'
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
falsy

The number 0 is false. Chapter 5.1's truth rule, and the reason if (NF) works as a non-empty test.

Exercise 2 — Classify with a chain

Classify each score as HIGH at 90 or above, MID at 70 or above, and LOW below that.

Azvya Education Pvt. Ltd.VLSI Mentor
scores.txt
alu 95
fifo 72
uart 88
spi 45
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 >= 90) print $1, "HIGH"; else if ($2 >= 70) print $1, "MID"; else print $1, "LOW" }' scores.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu HIGH
fifo MID
uart MID
spi LOW

Thresholds descending, so each branch is reachable.

Exercise 3 — Debug a wrong count

An engineer counts passing tests and gets 4 from a file with two passes. Their command:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 >= 80) print $1; count++ } END { print "count =", count+0 }' scores.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu
uart
count = 4

The if governs only the print. count++ is a separate statement in the same action, so it runs for all four records. Note that the two printed names already contradict the count — the output contains its own disproof.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 >= 80) { print $1; count++ } } END { print "count =", count+0 }' scores.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu
uart
count = 2

Exercise 4 — The boundary

Both commands below are run against two tests that scored exactly 80. Predict each, then state which policy each implements.

Azvya Education Pvt. Ltd.VLSI Mentor
boundary.txt
alu 80
fifo 80
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '$2 > 80 { n++ } END { print n+0, "tests above 80" }' boundary.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
0 tests above 80
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '$2 >= 80 { n++ } END { print n+0, "tests at or above 80" }' boundary.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
2 tests at or above 80

Zero against two, from the same data. The labels are doing real work here — each output states the rule it applied, so the two cannot be confused when they appear in a report.

Exercise 5 — Debug a dangerous classification

A regression sign-off report says all three tests passed. One of them was never scored. Find the bug.

Azvya Education Pvt. Ltd.VLSI Mentor
scores_bad.txt
alu 95
fifo n/a
uart 88
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 >= 80) print $1, "PASS"; else print $1, "FAIL" }' scores_bad.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu PASS
fifo PASS
uart PASS

fifo has no score and is reported as passing. "n/a" is not a numeric string, so awk compared as text, and n (0x6e) sorts above 8 (0x38).

Confirm the mechanism rather than assuming it:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk 'BEGIN { print ("n/a" >= "80"), ("-" >= "80"), ("TBD" >= "80") }'
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
1 0 1

n/a and TBD compare as true; - compares as false. The placeholder's spelling decides the verdict.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 !~ /^-?[0-9]+(\.[0-9]+)?$/) print $1, "NO_SCORE"; else if ($2 >= 80) print $1, "PASS"; else print $1, "FAIL" }' scores_bad.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu PASS
fifo NO_SCORE
uart PASS

Exercise 6 — Engineering application

Produce a sign-off summary with three categories, a visible denominator, and a non-zero exit status if any test was unscored — so a calling script cannot ignore it.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '$2 !~ /^-?[0-9]+(\.[0-9]+)?$/ { nodata++; next } $2 >= 80 { pass++; next } { fail++ } END { printf "%d pass, %d fail, %d unscored, of %d tests (threshold >= 80)\n", pass+0, fail+0, nodata+0, NR; if (nodata) exit 3 }' scores_bad.txt
echo "status: $?"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
2 pass, 0 fail, 1 unscored, of 3 tests (threshold >= 80)
status: 3

Everything a reviewer needs: three categories that sum to the denominator, the threshold stated, and an exit status that makes the unscored test impossible to overlook in automation. exit is Chapter 5.6's subject.

On clean data the same command exits 0:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '$2 !~ /^-?[0-9]+(\.[0-9]+)?$/ { nodata++; next } $2 >= 80 { pass++; next } { fail++ } END { printf "%d pass, %d fail, %d unscored, of %d tests (threshold >= 80)\n", pass+0, fail+0, nodata+0, NR; if (nodata) exit 3 }' scores.txt
echo "status: $?"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
2 pass, 2 fail, 0 unscored, of 4 tests (threshold >= 80)
status: 0

Exercise 7 — Challenge: prove a branch is reachable

An ascending chain makes later branches unreachable (section 4). Write a command that proves which branches a chain can actually reach, rather than inspecting it by eye.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 >= 70) { b="C"; hit["C"]++ } else if ($2 >= 80) { b="B"; hit["B"]++ } else if ($2 >= 90) { b="A"; hit["A"]++ } else { b="F"; hit["F"]++ } } END { split("A B C F", g, " "); for (i=1; i<=4; i++) printf "%s: %d%s\n", g[i], hit[g[i]]+0, (hit[g[i]] ? "" : "   <- NEVER TAKEN") }' scores.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
A: 0   <- NEVER TAKEN
B: 0   <- NEVER TAKEN
C: 3
F: 1

Two of four branches were never taken on this input, which is the signature of the ascending-chain bug. The descending version reaches three of four:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
awk '{ if ($2 >= 90) { hit["A"]++ } else if ($2 >= 80) { hit["B"]++ } else if ($2 >= 70) { hit["C"]++ } else { hit["F"]++ } } END { split("A B C F", g, " "); for (i=1; i<=4; i++) printf "%s: %d%s\n", g[i], hit[g[i]]+0, (hit[g[i]] ? "" : "   <- NEVER TAKEN") }' scores.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
A: 1
B: 1
C: 1
F: 1

All four reached. Arrays, split() and for are Modules 6 and 8 and Chapter 5.5 — the point here is the technique, which is the same one real coverage tools use: instrument the branches and count them, rather than arguing about the logic.

A branch showing 0 is not automatically a bug — it may simply be a case this input lacks. What it tells you is where to look, and a branch that is 0 across every input you have is either dead code or an untested path, both of which are worth knowing about.

14. Summary

  • if (condition) statement, parentheses required, and a semicolon before else.
  • else if chains test top to bottom and stop at the first match. Order thresholds descending or the later branches become dead code.
  • Without braces, if governs exactly one statement. The next statement runs unconditionally — identical output lines, wrong count, no error.
  • Indentation means nothing to awk. Only braces group.
  • > 80 and >= 80 disagree about exactly 80. Write the rule into the output so the policy is auditable.
  • Any expression is a condition — comparisons, &&/||, a regex match, or a bare value using Chapter 5.1's truth rule.
  • ?: supplies a value; if/else chooses an action.
  • A malformed field compared against a number is compared as text. n/a is reported as PASS, - as FAIL — the same bug, with the verdict decided by the placeholder's spelling.
  • Validate the shape first and give unusable data its own category. Three outcomes, summing to the denominator.
  • A pattern decides whether an action runs; if decides which statement runs. Anything needing an else needs if.

You can now classify records, and keep a classification honest about the data it was given.

Every guard so far has examined one field at a time. Chapter 5.5 — for and while Loops covers repetition: walking every field of a record whatever its width, the off-by-one that drops the last field, the index that returns the entire record instead of a field, and the loop that runs once even though its condition was false from the start.

Where this fits

Part of the awk curriculum.