!/bin/sh

anniv - generate anniversary reminders for agenda.txt

SPDX-FileCopyrightText: 2023 Daniel Kalak

SPDX-License-Identifier: GPL-3.0-or-later

This program reads lines from stdin and prints lines to stdout,

sorted. It expects the input lines to be of a format like this:

John Doe (my best friend) (* 1983-06-21)

These could be the first lines of a group of text files (e.g. with

contact information) that you could assemble with "head -qn1 *.txt".

Then, if the current year is 2023, the output would look like this:

2023-06-21 * John Doe (my best friend) (1983, 40)

If the year specified in the input is 0000 (i.e. if you had

"0000-06-21" in the example), the last parenthesis in the output (i.e.

" (1983, 40)" in the example) is omitted. (This is for cases where the

year is unknown.)

You can specify an arbitrary "current year" and an arbitrary symbol on

the command line. The symbol needs to be a Basic Regular Expression as

used by GNU sed. (For example, you could use "+" for deaths or "oo"

for marriages, etc.) By default, the current year at invocation and

the symbol "*" (to symbolize a birthday) are used.

The program only checks if there is a space followed by an opening

parenthesis (i.e. " (") at some point in an input line, and if that is

the case, it checks if there is the symbol followed by a space

followed by an ISO date (e.g. "* 1983-06-21") at some point after that

parenthesis (but before it is closed, if it ever is). Everything

before the " (" is treated as the "name", and everything else (other

than the date) is discarded. This lets you put arbitrary stuff into

the parenthesis (e.g. multiple dates with different symbols) or after

it.

This program depends on GNU awk, the GNU coreutils, and GNU sed. It

exits 0 on success and 1 on bad usage. If it encounters an input line

that is not in the format specified above, it redirects it to stderr,

along with a warning; this does not affect the other output lines (on

stdout) and the program still exits 0.

usage_quit() {

cat <<- EOF >&2

Usage: $0 [YEAR [SYMBOL]]

EOF

exit 1

}

year="${1:-$(date +%Y)}"

symbol="${2:-*}"

isodate='[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]'

case "$year" in

[0-9][0-9][0-9][0-9]) ;;

esac

sed '

s/\(.*\) ([^)]*\('"$symbol"'\) \('"$isodate"'\).*/\3 \2 \1/

t

s/^/ERROR/' |

At this stage in the pipeline, the example input line given above

would look like "1983-06-21 * John Doe (my best friend)". Faulty input

lines have a prepended "ERROR" tag (without separators) and are left

unchanged otherwise.

while read -r line

do

case "$line" in

ERROR*) printf 'Wrong input format: %s\n' "${line#ERROR}" >&2 ;;

*) printf '%s\n' "$line"

esac

done |

At this stage in the pipeline, the faulty lines prepended with "ERROR"

have been redirected to stderr.

awk -v "year=$year" '

{

birthyear = substr($0, 1, 4)

sub(birthyear, year)

if (birthyear != "0000")

	$0 = $0 " (" birthyear ", " year-birthyear ")"

print

}' |

At this stage in the pipeline, the "birth" year at the beginning of a

line has been replaced with the current year, and the " (1983, 40)"

parenthesis in the example has been appended for all years that are

not "0000". All that is left to do is to sort.

LC_ALL=C sort

Proxy Information
Original URL
gemini://dkalak.de/software/anniv.sh
Status Code
Success (20)
Meta
text/plain
Capsule Response Time
108.828758 milliseconds
Gemini-to-HTML Time
1.775541 milliseconds

This content has been proxied by September (3851b).