#!/usr/bin/gawk -f
# Add multilevel heading numbers to HTML headings.
# Ian E. Gorman 2023
# This AWK program assumes that the input is valid HTML.
# The program is written for GNU AWK and may not work in other versions of AWK.
# The program has not been tested in POSIX AWK
# AWK is often considered to be a line-oriented language that iterates over
# the lines in a text file. AWK is actually a record-oriented language.
# The default record separator is a platform-specific sequence of
# characters: "\n", "\r\n". or "\r".
# Splitting input lines on '<' instead of '\n' places each tag at the
# beginning of a line, but ddrops the '<' character. A new '<"
# character must be inserted in the corresponding output line.
BEGIN {
ORS = RS = "<" # Change record separators from default to '<'
level = 0 # begin outside any headings
LEVEL_MAX = 6 #
to
for (i = 1; i <= LEVEL_MAX; i++) {
number[i] = 0
}
}
# Enter heading, output the start tag, set heading level
match($0, /^[Hh]([1-6])[^>]*>/, part) != 0 { # heading start tag
print "" # write the record separator (ORS = "<")
printf("%s", substr($0, 1, RLENGTH)) # write the rest of the tag
level = part[1] # entering heading, get the level from tag
number[level]++
for (i = level + 1; i <= LEVEL_MAX; i++) number[i] = 0
printf("%d", number[1])
for (i = 2; i <= level; i++) printf(".%d", number[i])
printf(" ")
printf(substr($0, RLENGTH + 1)) # output the remaining data
next
}
# Exit heading: output end tag, unset heading level
/^\/[Hh][1-6][^>]*>/ { # Heading end tag
print "" # write the record separator (ORS = "<")
printf("%s", $0) # write rest of tag and the following input data
LEVEL = 0 # leaving heading
next
}
# First record in file is not preceded by a record separator
FNR == 1 {
# No need to write a record separator (ORS = "<")
printf("%s", $0)
next
}
# All other input records are preded by a record separator
{
print "" # write the record separator (ORS = "<")
printf("%s", $0)
next
}