Mit Shellscript User in verschiedenen Dateien abgleichen

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
toberkel
Beiträge: 155
Registriert: 19.05.2003 08:44:53
Wohnort: Lummerland

Mit Shellscript User in verschiedenen Dateien abgleichen

Beitrag von toberkel » 20.06.2007 10:01:49

Hi.

Ich stehe leider vor einem kleinen Problem und hoffe jemand kann mir evtl. helfen.

Ich habe zwei Dateien in dem Format <vorname>_<nachname>. Allerdings sind dies unterschiedlich geschrieben. z.B. VorNAMe_NAchnAME usw. Also nicht direkt so ;) Aber in beiden Dateien halt unterschiedlich. Die Datei1 enthällt alle User die existieren, die Datei2 enthällt alle User die ein VPN-Zertifikat haben. Mein Problem ist nur, das ich nun rausfinden muss ob es in Datei2 (VPN) User gibt, die nicht in Datei1 existieren. Dabei muss ich natürlich auf unterschiedliche schreibweisen achten und in der Datei2 (VPN) kann es sein das vor dem Namen evtl noch ein Wort steht, das sollte auch berücksichtigt werden.

Kann mir da jemand evtl. helfen? Komme da nicht weiter.

mfg,

toberkel
--
Rechtschreibfehler dienen der allgemeinen Belustigung,
und sind daher beabsichtigt.

grb
Beiträge: 8
Registriert: 15.06.2007 11:16:27

Beitrag von grb » 20.06.2007 19:47:14

Hi,

puh, also das folgenden ist schnell hingeschmiert, das geht sicher 1000mal eleganter (ich kann weder sed noch awk):

Die Dateien mit denen ich das getestet habe sahen folgendermaßen aus:

Datei1(jene mit den Usern)

Code: Alles auswählen

nAme1_vorNAMe1
namE3_vorNAME3
name6_vorname6
name4_VORname4
Datei2 (jene mit VPN-Zertifizierungen)

Code: Alles auswählen

namE1_vorName1
name2_vorNAMe2
aaaa: NAME3_vorNAME3
bbbb: name4_vorname4
name5_VORname5
Die Ausgabe sollte lauten:

Code: Alles auswählen

name2_vorNAMe2
name5_VORname5
da diese Usern nicht in datei1 vorkommen.

Hier das grausame Skript (ersetze datei{1,2} durch 'Datei mit Usern' 'Datei mit VPN-Zertifizierungen' in der Reihenfolge (ansonsten ist das Ergebnis genau andersrum):

Code: Alles auswählen

diff -i datei{1,2} | awk '{ if (NF == 3) { print $1$3 } else { print $1$2 } }' | sort | uniq -iu --skip-chars=1 | grep '^>'
Hoffe, das läuft bei Dir :), wenn es das tut, kannst du das ganze ja in ein kleines skript packen.

Gruß

toberkel
Beiträge: 155
Registriert: 19.05.2003 08:44:53
Wohnort: Lummerland

Beitrag von toberkel » 20.06.2007 20:14:06

Hmm... Irgendwie läuft das nicht ;) Bei meiner VPN datei wäre das z.b. so: DEACTIVIATEDVornamE_NachNAMe.
Kann es sein das es deswegen nicht klappt? Die Dateien heissen vpn_user und intranet_user...
--
Rechtschreibfehler dienen der allgemeinen Belustigung,
und sind daher beabsichtigt.

grb
Beiträge: 8
Registriert: 15.06.2007 11:16:27

Beitrag von grb » 20.06.2007 23:00:40

Hi,

ja daran liegt es. Es ist kein Feldtrenner vorhanden, da zwischen 'DEACTIVATED' und dem Rest kein Leerzeichen oder sonstiger Feldtrenner ist und man damit immer alles matcht. Hinzu kommt, das meines Wissens nach awk keine Backreferences kennt und sed keiner Alternierung, d.h. man kommt mit beidem nicht weiter, weshalb ich jetzt meine dürtigen Perl-Skills verwenden musste.
Also vorausgesetzt die Schlüsselwörter die vor den Namen in der vpn_users-Datei stehen lauten ACTIVATED und DEACTIVATED oder eben gar nichts, sollte folgendes Skript hinhauen. Falls andere Schlüsselwörter verwendet werden oder welche hinzugefügt werden müssen, musst Du das Skript ein wenig abändern. Aufruf mit

Code: Alles auswählen

 ./skript vpn_users internet_users 

Code: Alles auswählen

#!/usr/bin/perl
use warnings;
 
  sub inter {
     my %seen;
     for my $href (@_) {
        while (my $k = each %$href) {
           $seen{$k}++;
        }
     }
     while (($key, $value) = each %seen) {
        if ($seen{$key} == @_) {
           $result{$key} = 1;
        }
     }
     return %result;
  }
 
  my (%vpn_users, %intranet_users, %result);
  open F, $ARGV[0];
  while( defined (my $zeile = <F>) ) {
     $zeile =~ s/^(DEACTIVATED|ACTIVATED)(.*)/$2/;
     $vpn_users{"\L$zeile"} = 1;
  }
  close F;
 
  open (F, $ARGV[1]);
  while( defined (my $zeile = <F>) ) {
     $zeile =~ s/^(DEACTIVATED|ACTIVATED)(.*)/$2/;
     ${intranet_users}{"\L$zeile"} = 1;
  }
  close F;
 
  %result = inter(\%vpn_users, \%intranet_users);
 
  while (($key, $value) = each %vpn_users) {
     if (defined $result{$key}) {
        next;
     } else {
        print $key;
     }
 }
So, mal schauen wie das nun läuft.

toberkel
Beiträge: 155
Registriert: 19.05.2003 08:44:53
Wohnort: Lummerland

Beitrag von toberkel » 21.06.2007 10:19:54

Da kommt als Output genau garnichts :( Ich poste mal paar Beispiele...

intranet_users:

Code: Alles auswählen

Hans_Müller
Gretchen_Schmitt Koster
Nicole_Schneider
Oliver_Hoß Meier
vpn_users

Code: Alles auswählen

hans_mueller
gretchen_schmitt-koster
Manfred_Preuss
DEACTIVATEDnicole_schneider
TOR
Wenn das Script richtig läuft, sollte es nur Manfred_Preuss und TOR anzeigen da die nicht in der intranet_users nicht vorhanden sind... :( Ich komme da echt nicht weiter...

mfg,

toberkel
--
Rechtschreibfehler dienen der allgemeinen Belustigung,
und sind daher beabsichtigt.

grb
Beiträge: 8
Registriert: 15.06.2007 11:16:27

Beitrag von grb » 21.06.2007 19:59:24

Hi, nochmals, also das Skript funktioniert eigentlich ganz gut, jedoch halt nur wenn man bestimmte Namensformate einhält. Dass du beispielsweise Umlaute mal so, mal so schreibst oder das etwa einmal ein Bindestrich da ist und einmal nich, davon wusste ich ja nichts. All diese Sachen müsste man berücksichtigen, weshalb ich ernsthaft glaube, dass dein Anliegen nur mit viel Aufwand realisierbar ist. Du solltest solche Dateien immer nach einem bestimmten Format ausrichten und (eigene) Konventionen einhalten, damit solche Aufgaben auch durchführbar sind (wie z.B. /etc/passwd).

Gruß

toberkel
Beiträge: 155
Registriert: 19.05.2003 08:44:53
Wohnort: Lummerland

Beitrag von toberkel » 22.06.2007 09:34:17

Hi.

Das mit den Konventionen ist klar, leider aber hier nicht so leicht umsetzbar. Die Daten der Intranet-User kommen aus einer MSSQL-DB und werden so in unserem Intranet angezeigt und verwendet. Die Daten der VPN-User kommen von einer Linux-FW. Nun muss ich gucken wie die beiden am besten abgeglichen werden... :( Falls mal Unstimmigkeiten auftreten oder vergessen wurde ein VPN-Zertifikat zu deaktivieren...

mfg,

toberkel
--
Rechtschreibfehler dienen der allgemeinen Belustigung,
und sind daher beabsichtigt.

Antworten