#!/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 < -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