townandmail/townandmail.sh

214 lines
6.9 KiB
Bash
Executable file

#!/bin/bash
# file: townandmail.sh
# user: bernd@nr18.space
# date: 20.08.2021
#
# funktionsweise:
#
# zur vorbereitung werden aus der datei dfbasic plz, ort und
# gemeindeschlüssel extrahiert und alle doppelten einträge entfernt. der
# daraus resultierende datensatz wird in der datei $GS_FILE gespeicher.
#
# das script läuft dann zuerst durch die datei mit den email adressen. jeder
# datensatz wird in die datei $TMP_OUT geschieben. gleichzeitig wird
# versucht mit plz und ort des datensatzes aus der datei $GS_FILE den
# gemeindeschlüssel zu bekommen. gelingt dies, wird der schlüsel zusammen
# mit der email adresse in die datei $GS_MAIL geschrieben.
#
# im zweiten durchlauf gehen wir durch die datei ohne mail-adressen. zuerst
# überprüfen wir, ob es eventuell schon einen äquivalenten datensatz in der
# ausgabedatei ($TMP_OUT) gibt. gibt es noch keinen datensatz, versuchen wir
# für plz und ort einen gemeindeschlüssel zu bekommen. haben wir einen
# gemeindeschlüsssel, schauen wir in der datei $GS_MAIL nach, ob dort ein
# eintrag für diesen schlüssel existiert. im erfolgsfall ordnen wir die dort
# gefundene email adresse dem datensatz zu und speichern ihn in $TMP_OUT.
# gibt es keinen gemeindeschlüssel oder keine dazu gehörige email adresse,
# wird der datensatz mit einer kurzen fehlermeldung in $FALLOUT gespeichert.
#
# abschließend werden die gewonnen daten je nach option in eine datei
# geschrieben oder nach stdout ausgegeben.
#
# todo:
#
# 1.) rückgabewerte der einzelnen schritte überprüfen!
umask=077
PROGRAMM_NAME=$(basename "$0")
DEBUG=0
VERBOSITY=0
NEW_GS=0
KEEP_FAILS=0
OHNE_MAIL=""
MIT_MAIL=""
OUTPUT=""
GS_FILE="gemeindeschluessel.csv"
TMP_OUT="tam_output.csv"
GS_MAIL="tam_gs_mail.csv"
FALLOUT="tam_fallout.csv"
DATASETS=0
MATCH=0
FAILS=0
usage_and_exit() {
# ausgabe einer kurzen hilfe
cat <<EOF
Usage: $PROGRAMM_NAME [-d -g -h -k -o outputfile -v] -i input -m input
-d runs in debug mode
-g creates new community keys file from dfbasic and exits
-h displays short help and exits
-o outputfile write output to file <outputfile>
-i inputfile inputfile without email addresses
-k keeps file with fails
-m inputfile inputfile with email addresses
-v run in verbose mode
EOF
exit $1
}
msg() {
# ausgabe von meldungen mit zeilenumbruch.
if [ "$VERBOSITY" -eq 1 ] ; then
printf "%s\n" "$@"
fi
}
msg_start() {
# ausgabe von meldungen ohne zeilenumbruch.
if [ "$VERBOSITY" -eq 1 ] ; then
printf "%s" "$@"
fi
}
gs_factory() {
# zieht aus der datei dfbasic die spalten 1,3 und 11 (plz, ortsname,
# gemeindeschlüssel), sortiert und entfernt doppelte einträge, und
# schreibt das ergebnis in die datei $GS_FILE. diese datei wird beim
# beenden nicht gelöscht und kann wieder verwendet werden.
msg_start "Create new community key file ... "
awk -F ';' '$1 ~ /^[0-9]/ { print $1","$3","$11 }' dfbasic | sort -u >$GS_FILE
msg "OK"
gs=$(wc -l $GS_FILE | cut -d " " -f 1)
msg "Found $gs community keys."
}
# start des programmes
# CLI optionen auswerten, eventuell datei mit den gemeindeschlüsseln neu
# erstellen und leere temporäre dateien erstellen.
while getopts dghi:km:o:v opt ; do
case $opt in
d) DEBUG=1;VERBOSITY=1;;
g) NEW_GS=1;;
h) usage_and_exit 0;;
i) OHNE_MAIL="$OPTARG";;
k) KEEP_FAILS=1;;
m) MIT_MAIL="$OPTARG";;
o) OUTPUT="$OPTARG";;
v) VERBOSITY=1;;
*) usage_and_exit 0;;
esac
done
if [ "$NEW_GS" -eq 1 ] ; then
gs_factory
exit 0
fi
if [ -z "$OHNE_MAIL" ] || [ -z "$MIT_MAIL" ] ; then
echo "Error: One or both input files are missing."
usage_and_exit 1
fi
msg "Use input files $OHNE_MAIL, $MIT_MAIL."
msg "Verbosity: $VERBOSITY, DEBUG: $DEBUG, KEEP FAILS: $KEEP_FAILS."
printf "%s" "" >$GS_MAIL
printf "%s" "" >$TMP_OUT
printf "%s" "" >$FALLOUT
# wenn die option debug gesetzt wurde, sollen die temporären dateien
# erhalten bleiben. per default werden sie gelöscht.
trap "exit 1" SIGINT SIGHUP SIGTERM SIGQUIT SIGPIPE
if [ "$DEBUG" -eq 0 ] ; then
if [ "$KEEP_FAILS" -eq 1 ] ; then
trap 'rm -f "$GS_MAIL" "$TMP_OUT"' EXIT
else
trap 'rm -f "$GS_MAIL" "$FALLOUT" "$TMP_OUT"' EXIT
fi
fi
# wir schneiden aus beiden eingabedateien die plz und den ort heraus,
# sortieren die daten, entfernen doppelte einträge und zählen diese.
DATASETS=$(awk -F ',' '{ print $2","$1 }' "$OHNE_MAIL" "$MIT_MAIL" | sort -u | wc -l)
msg "Found $DATASETS unique records."
# zuerst gehen wir duch die datei mit den email-adressen. dabei versuchen
# wir für jede zeile für die plz und den ort in der datei mit den
# gemeindeschlüssel ($GS_FILE) diesen schlüssel zu finden. gelingt uns
# dies, ordnen wir die e-mail adresse diesem schlüssel zu und schreiben das
# ergenis in eine datei ($GS_MAIL). alle zeilen werden in die datei $TMP_OUT
# geschriben.
msg_start "Try to match postalcode and townname with community key ... "
while IFS=, read -r ort plz mail; do
gs=$(grep "$plz" $GS_FILE | grep ",$ort," | cut -d ',' -f 3)
if [ -z "$gs" ] ; then
FAILS=$(( FAILS + 1 ))
else
MATCH=$(( MATCH + 1 ))
echo "$gs,$mail" >>$GS_MAIL
fi
echo "$plz,$ort,$mail" >>$TMP_OUT
done < "$MIT_MAIL"
msg "OK"
msg "$MATCH postalcodes and townname matsches"
msg "$FAILS postalcode and townname doesnt matchs"
# im zweiten durchlauf gehen wir durch die datei ohne mail-adressen. zuerst
# überprüfen wir, ob es eventuell schon einen eintrag in der ausgabedatei
# ($TMP_OUT) gibt. Gibt es keinen, versuchen wir für plz und ort einen
# gemeindeschlüssel zu bekommen. wenn dies gelingt, holen wir uns aus der
# datei mit den gemeindeschlüsseln die dafür (hoffentlich bereits bekannte)
# email-adresse. Könnte man vielleicht in einem durchlauf erledigen!
msg_start "Try to match email with community key ... "
MATCH=0
FAILS=0
while IFS=, read -r ort plz ; do
resp=$(grep "$plz" $TMP_OUT | grep ",$ort,")
if [ -z "$resp" ] ; then
gs=$(grep "$plz" $GS_FILE | grep ",$ort," | cut -d ',' -f 3)
if [ -z "$gs" ] ; then
FAILS=$(( FAILS + 1 ))
echo "$plz,$ort,cant get community key" >>$FALLOUT
else
mail=$(grep "$gs" $GS_MAIL | cut -d ',' -f 2)
if [ -z "$mail" ] ; then
FAILS=$(( FAILS + 1 ))
echo "$plz,$ort,cant get email for $gs" >>$FALLOUT
else
echo "$plz,$ort,$mail" >>$TMP_OUT
MATCH=$(( MATCH + 1 ))
fi
fi
fi
done < "$OHNE_MAIL"
msg "OK"
msg "$MATCH community codes successfull matched"
msg "$FAILS failed"
match=$(wc -l $TMP_OUT | cut -d " " -f 1)
fail=$(wc -l $FALLOUT | cut -d " " -f 1)
printf "%5s unique records.\n" "$DATASETS"
printf "%5s records successfull proceeded.\n" "$match"
printf "%5s records failed.\n" "$fail"
if [ -z "$OUTPUT" ] ; then
sort -u $TMP_OUT
else
sort -u $TMP_OUT > "$OUTPUT"
fi