awk match and substr: Extract Part of a Field
awk match(s, re) locates a regex in a string and sets RSTART and RLENGTH; substr(s, m, n) slices out a piece.
When the value you want is buried inside a field, like a version number in a tag, match plus substr extracts it without a separate tool.
What it does
match(string, regex) returns the position of the first match (0 if none) and sets RSTART to that position and RLENGTH to the match length. substr(string, start, length) returns a substring; start is 1-based and length is optional (rest of string if omitted).
Common usage
# extract a semver from a tag like release-1.2.3
awk '{ if (match($0, /[0-9]+\.[0-9]+\.[0-9]+/))
print substr($0, RSTART, RLENGTH) }' tags.txt
# first 7 chars of a commit SHA
awk '{print substr($1, 1, 7)}' commits.txt
# everything after the first colon
awk '{print substr($0, index($0, ":") + 1)}' kv.txtFunctions and variables
| Item | What it does |
|---|---|
| match(s, /re/) | Return match position (0 if none), set RSTART and RLENGTH |
| RSTART | Start position of the last match |
| RLENGTH | Length of the last match (-1 if no match) |
| substr(s, m) | Substring from position m to end (1-based) |
| substr(s, m, n) | Substring of length n starting at position m |
| index(s, t) | Position of substring t in s, or 0 |
In CI
match plus substr extracts a version or hash from messy tool output, which you can then push to $GITHUB_OUTPUT. Always guard substr with an if (match(...)) check so a non-matching line does not slice the wrong bytes.
Common errors in CI
awk string positions are 1-based, not 0-based; substr($0, 0, 3) behaves oddly because position 0 is before the string. When match fails, RLENGTH is -1, so substr($0, RSTART, RLENGTH) returns an empty or unexpected string; check the match return value first. Off-by-one slices usually come from forgetting the +1 after an index() position.