pixel24
Anmeldungsdatum: 20. Februar 2008
Beiträge: 473
|
Hallo zusammen, ich hoffe ich habe die Frage hier richtig platziert. Es geht zwar zuerst um den Aufbau der VCARD aber am Ende dann wohl um die "Überarbeitung" per Shell Befehl oder Script. Es gibt etwas Vorgeschichte. Ein Bekannter hat auf seinem iPhone seine ganzen Kontakte gespeichert welche schon aber über Jahre hinweg von einem Handy auf das nächste übertragen wurden. Angefangen beim Nokia XY. Aus irgend einem Grund den ich nicht verstanden habe hat er aber beim ersten Nokia den Vorname in das Feld Nachname eingegeben und umgekehrt. Ich habe die Adressen nun am iPhone als VCARD exportiert um sie in ein Google Pixel4 zu importieren. Der Import klappt auch nur sind natürlich hier auch Vor- und Nachname vertauscht. Nun habe ich mir den Aufbau der VCARD angeschaut und auch die Syntax bei Wikipedia https://de.wikipedia.org/wiki/VCard nachgeschaut. Der Export hat folgenden Aufbau:
1
2
3
4
5
6
7
8
9
10
11
12
13 | BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//iOS 13.1.2//EN
N:Vorname;Nachname;;;
FN:Nachname Vorname
ORG:Firnem-Name;
item1.EMAIL;type=INTERNET;type=pref:vorname.nachname@firmenname.de
TEL;type=CELL;type=VOICE;type=pref:+49 7123-10 456789
TEL;type=IPHONE;type=CELL;type=VOICE:+49 172 567890
TEL;type=OTHER;type=FAX:+49 (0) 7123 7123-99
item2.ADR;type=HOME;type=pref:;;Musterstrasse. 4;Musterhausen;;76767;
REV:2019-10-14T00:51:11Z
END:VCARD
|
Ich vermute mal dass ich vor dem Import in den Zeilen N: und FN: die Reihenfolge von Vorname und Nachname umkehren muss, oder? Lässt sich so etwas per Shell in einem Rutsch erledigen? Es gibt jedoch einen Sonderfall. In manchen Datensätzen steht nur im Feld Nachname etwas drin. Beispiel:
diese sollen einfach so bleiben. Oder gibt es eine Software mit der ich so eine Stapel-Verarbeitung durchführen kann? Viele Grüße
pixel24
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17552
Wohnort: Berlin
|
Dafür ist sed das Mittel der Wahl:
| echo "PRODID:-//Apple Inc.//iOS 13.1.2//EN
N:Vorname;Nachname;;;
FN:Nachname Vorname
ORG:Firnem-Name;" | sed -r 's/^N:([^;]+);([^;]+);(.*)/N:\2;\1;\3/; s/^FN:([^ ]+) ([^ ]+)$/FN:\2 \1/;'
PRODID:-//Apple Inc.//iOS 13.1.2//EN
N:Nachname;Vorname;;;
FN:Vorname Nachname
ORG:Firnem-Name;
|
Wenn das alles in einer Datei steht, und die Datei chronologisch aufgebaut ist, dann brauchst Du nur noch die Zeile zu ermitteln, in der die erste VCard beginnt, die und die letzte endet, die behandelt werden müssen. Angenommen es geht um die Zeilen 1-456: | sed -r -i.bak '1,456 s/^N:([^;]+);([^;]+);(.*)/N:\2;\1;\3/; 1,456s/^FN:([^ ]+) ([^ ]+)$/FN:\2 \1/;' vCard.dat
|
(Ohne Gewähr - backup often!)
|
pixel24
(Themenstarter)
Anmeldungsdatum: 20. Februar 2008
Beiträge: 473
|
user_unknown schrieb: Wenn das alles in einer Datei steht, und die Datei chronologisch aufgebaut ist, dann brauchst Du nur noch die Zeile zu ermitteln, in der die erste VCard beginnt, die und die letzte endet, die behandelt werden müssen. Angenommen es geht um die Zeilen 1-456: | sed -r -i.bak '1,456 s/^N:([^;]+);([^;]+);(.*)/N:\2;\1;\3/; 1,456s/^FN:([^ ]+) ([^ ]+)$/FN:\2 \1/;' vCard.dat
|
(Ohne Gewähr - backup often!)
Ja, steht alles in einer Datei untereinander. Die Reihenfolge ist alphabetisch oder was meinst Du mit "chronologisch" ? Ja, habe die Export-Datei als Backup und werde den Import anschließend ohnehin erst auf einem Test-Account einlesen um zu sehen was raus kommt.
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17552
Wohnort: Berlin
|
pixel24 schrieb: user_unknown schrieb: Wenn das alles in einer Datei steht, und die Datei chronologisch aufgebaut ist, dann brauchst Du nur noch die Zeile zu ermitteln, in der die erste VCard beginnt, die und die letzte endet, die behandelt werden müssen. Angenommen es geht um die Zeilen 1-456: | sed -r -i.bak '1,456 s/^N:([^;]+);([^;]+);(.*)/N:\2;\1;\3/; 1,456s/^FN:([^ ]+) ([^ ]+)$/FN:\2 \1/;' vCard.dat
|
(Ohne Gewähr - backup often!)
Ja, steht alles in einer Datei untereinander. Die Reihenfolge ist alphabetisch oder was meinst Du mit "chronologisch" ?
Was man mit chronologogisch so meint - also nicht alphabetisch. Ich dachte die ältesten Versionen seien auf einem NokiaXY erzeugt worden und falsch und dann vielleicht ab VCard 78 in der richtigen Reihenfolge. Sonst muss man ja irgendwie anders unterscheiden können, ob die Namen umgedreht werden müssen oder nicht. Als nächstes bietet sich vielleicht das REV-Feld an - bezieht sich das auf das Datum des Anlegens des Eintrags, der letzten Änderung oder was ist das? Sehr kompliziert wäre es schon, das ganze mit einem Vornamensregister abzugleichen, nur gibt es ja Namen wie Herrmann, die sowohl als Vor- als auch als Nachname vorkommen. Oder ein interaktives Programm, das einen zu jedem Namen kurz fragt, ob geändert werden soll, ja oder nein. Ein solches Programm wäre etwa ein Editor der reguläre Ausdrücke kennt (geany, scite, ...) bei dem man dann zwei Durchläufe hätte, einen für das N-, einen für das FN-Feld. Die Syntax ist da etwas abweichend, v.a. sind Such/Ersetzstring auf zwei Felder verteilt.
|
pixel24
(Themenstarter)
Anmeldungsdatum: 20. Februar 2008
Beiträge: 473
|
user_unknown schrieb: Was man mit chronologogisch so meint - also nicht alphabetisch. Ich dachte die ältesten Versionen seien auf einem NokiaXY erzeugt worden und falsch und dann vielleicht ab VCard 78 in der richtigen Reihenfolge. Sonst muss man ja irgendwie anders unterscheiden können, ob die Namen umgedreht werden müssen oder nicht. Als nächstes bietet sich vielleicht das REV-Feld an - bezieht sich das auf das Datum des Anlegens des Eintrags, der letzten Änderung oder was ist das? Sehr kompliziert wäre es schon, das ganze mit einem Vornamensregister abzugleichen, nur gibt es ja Namen wie Herrmann, die sowohl als Vor- als auch als Nachname vorkommen. Oder ein interaktives Programm, das einen zu jedem Namen kurz fragt, ob geändert werden soll, ja oder nein. Ein solches Programm wäre etwa ein Editor der reguläre Ausdrücke kennt (geany, scite, ...) bei dem man dann zwei Durchläufe hätte, einen für das N-, einen für das FN-Feld. Die Syntax ist da etwas abweichend, v.a. sind Such/Ersetzstring auf zwei Felder verteilt.
Der letzte VCARD-Export habe ich auf dem iPhone gemacht. Sieht so aus:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 | BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//iOS 13.1.2//EN
N:StauAnsage;ADAC;;;
FN:ADAC StauAnsage
TEL;type=CELL;type=VOICE;type=pref:2211
REV:2019-10-14T00:51:11Z
END:VCARD
BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//iOS 13.1.2//EN
N:Travel;ADAC;;;
FN:ADAC Travel
TEL;type=CELL;type=VOICE;type=pref:2525
REV:2019-10-14T00:51:11Z
END:VCARD
BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//iOS 13.1.2//EN
N:Verkehr;ADAC;;;
FN:ADAC Verkehr
TEL;type=CELL;type=VOICE;type=pref:2526
REV:2019-10-14T00:51:11Z
END:VCARD
...
BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//iOS 13.1.2//EN
N:;Auskunft;;;
FN:Auskunft
TEL;type=CELL;type=VOICE;type=pref:11833
REV:2019-10-14T00:51:11Z
END:VCARD
|
Wäre es möglch einfach immer die Felder zu tauschen, auch wenn eines Leer ist?
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17552
Wohnort: Berlin
|
Wieso probierst Du es nicht aus?
|
pixel24
(Themenstarter)
Anmeldungsdatum: 20. Februar 2008
Beiträge: 473
|
user_unknown schrieb: Wieso probierst Du es nicht aus?
Dazu fehlt mir das tiefer Wissen zu sed, awk .... ☹ wenn ich mir die Datensätze anschaue (Daten verändert) wie:
| BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//iOS 13.1.2//EN
N:Max;Musterman;;;
FN:Mustermann Max
TEL;type=CELL;type=VOICE;type=pref:+49 72385 12345678
TEL;type=IPHONE;type=CELL;type=VOICE:+49 178 12345678
REV:2019-10-14T00:51:11Z
END:VCARD
|
und: | BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//iOS 13.1.2//EN
N:;Alé-D2;;;
FN:Alé-D2
TEL;type=CELL;type=VOICE;type=pref:+49 174 456789
item1.ADR;type=HOME;type=pref:;;Prinzregentenstr. 147;München;;81677;Deutschland
item1.X-ABADR:de
REV:2019-10-14T00:51:11Z
END:VCARD
|
Dann sind es doch die beiden Zeilen:
| N:Max;Musterman;;;
FN:Mustermann Max
|
Ich vermute mal das N die einzelnen Namensfelder sind:
| N:[Nachname];[Vorname];;;
|
und:
der Anzeigename ist und im Fall:
Der Nachname im Feld für Vorname steht und der eigentliche Nachname fehlt, oder? Gibt es mit den Tools sed .... nun keine Möglichkeit diese beiden Felder nun "einfach": - Wenn beide gefüllt sind: In N die Position zu tauschen und in FN die Reihenfolg
- Wenn nur eines gefüllt ist: In N die Position zu tauschen und FN so belassen ? Viele Grüße
pixel24
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11179
Wohnort: München
|
pixel24 schrieb: user_unknown schrieb: Wieso probierst Du es nicht aus?
Dazu fehlt mir das tiefer Wissen zu sed, awk .... ☹
Dann nimm doch eine andere Sprache - man muss ja nicht alles mit archaischen Werkzeugen machen... 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | #!/usr/bin/env python3
import fileinput
for line in fileinput.input():
line = line.rstrip()
if line.startswith('N:'):
_, _, data = line.partition(':')
name_data = data.split(';')
print(f"N:{name_data[1]};{name_data[0]};{';'.join(name_data[2:])}")
change_names = TRue if all(name_data[:2]) else False
elif line.startswith('FN:'):
if change_names:
print(f"FN:{name_data[0]} {name_data[1]}")
else:
print(line)
else:
print(line)
|
$ python3 vcard_transform.py << EOF
BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//iOS 13.1.2//EN
N:Max;Musterman;;;
FN:Mustermann Max
TEL;type=CELL;type=VOICE;type=pref:+49 72385 12345678
TEL;type=IPHONE;type=CELL;type=VOICE:+49 178 12345678
REV:2019-10-14T00:51:11Z
END:VCARD
EOF
BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//iOS 13.1.2//EN
N:Musterman;Max;;;
FN:Max Musterman
TEL;type=CELL;type=VOICE;type=pref:+49 72385 12345678
TEL;type=IPHONE;type=CELL;type=VOICE:+49 178 12345678
REV:2019-10-14T00:51:11Z
END:VCARD
$ python3 vcard_transform.py << EOF
BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//iOS 13.1.2//EN
N:;Alé-D2;;;
FN:Alé-D2
TEL;type=CELL;type=VOICE;type=pref:+49 174 456789
item1.ADR;type=HOME;type=pref:;;Prinzregentenstr. 147;München;;81677;Deutschland
item1.X-ABADR:de
REV:2019-10-14T00:51:11Z
END:VCARD
EOF
BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//iOS 13.1.2//EN
N:Alé-D2;;;;
FN:Alé-D2
TEL;type=CELL;type=VOICE;type=pref:+49 174 456789
item1.ADR;type=HOME;type=pref:;;Prinzregentenstr. 147;München;;81677;Deutschland
item1.X-ABADR:de
REV:2019-10-14T00:51:11Z
END:VCARD
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12829
|
seahawk1986 schrieb:
Dann nimm doch eine andere Sprache - man muss ja nicht alles mit archaischen Werkzeugen machen...
Warum dann nicht gleich vcard nehmen?
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11179
Wohnort: München
|
Das hängt immer davon ab, wie komplex man es machen will - vcard erwartet standard-konforme Dateien, die Beispiele, die pixel24 gepostet hat, erfüllen dieses Kriterium nicht. Wenn die Reihenfolge der Felder immer wie in den Beispielen gegeben ist, kann man es sich außerdem sparen die komplette Datei im RAM zu halten und sie zeilenweise verarbeiten.
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17552
Wohnort: Berlin
|
Also mit einer kl. Änderung klappt es auch bei leeren Feldern:
| > cat vcards.txt | egrep "^F?N:"
N:Max;Musterman;;;
FN:Mustermann Max
N:;Alé-D2;;;
FN:Alé-D2
> cat vcards.txt | sed -r 's/^N:([^;]*);([^;]*);(.*)/N:\2;\1;\3/; s/^FN:([^ ]+) ([^ ]+)$/FN:\2 \1/;' | egrep "^F?N:"
N:Musterman;Max;;;
FN:Max Mustermann
N:Alé-D2;;;;
FN:Alé-D2
|
|
pixel24
(Themenstarter)
Anmeldungsdatum: 20. Februar 2008
Beiträge: 473
|
seahawk1986 schrieb: pixel24 schrieb: user_unknown schrieb: Wieso probierst Du es nicht aus?
Dazu fehlt mir das tiefer Wissen zu sed, awk .... ☹
Dann nimm doch eine andere Sprache - man muss ja nicht alles mit archaischen Werkzeugen machen...
Ich habe erst angefangen Bash-Script zu lernen. Also steht mir da noch nicht viel zur Auswahl. Werde dein Script Morgen gleich mal testen. Vielen Dank schon mal ☺
|
pixel24
(Themenstarter)
Anmeldungsdatum: 20. Februar 2008
Beiträge: 473
|
seahawk1986 schrieb: pixel24 schrieb: user_unknown schrieb: Wieso probierst Du es nicht aus?
Dazu fehlt mir das tiefer Wissen zu sed, awk .... ☹
Dann nimm doch eine andere Sprache - man muss ja nicht alles mit archaischen Werkzeugen machen... 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | #!/usr/bin/env python3
import fileinput
for line in fileinput.input():
line = line.rstrip()
if line.startswith('N:'):
_, _, data = line.partition(':')
name_data = data.split(';')
print(f"N:{name_data[1]};{name_data[0]};{';'.join(name_data[2:])}")
change_names = TRue if all(name_data[:2]) else False
elif line.startswith('FN:'):
if change_names:
print(f"FN:{name_data[0]} {name_data[1]}")
else:
print(line)
else:
print(line)
|
$ python3 vcard_transform.py << EOF
BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//iOS 13.1.2//EN
N:Max;Musterman;;;
FN:Mustermann Max
TEL;type=CELL;type=VOICE;type=pref:+49 72385 12345678
TEL;type=IPHONE;type=CELL;type=VOICE:+49 178 12345678
REV:2019-10-14T00:51:11Z
END:VCARD
EOF
BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//iOS 13.1.2//EN
N:Musterman;Max;;;
FN:Max Musterman
TEL;type=CELL;type=VOICE;type=pref:+49 72385 12345678
TEL;type=IPHONE;type=CELL;type=VOICE:+49 178 12345678
REV:2019-10-14T00:51:11Z
END:VCARD
$ python3 vcard_transform.py << EOF
BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//iOS 13.1.2//EN
N:;Alé-D2;;;
FN:Alé-D2
TEL;type=CELL;type=VOICE;type=pref:+49 174 456789
item1.ADR;type=HOME;type=pref:;;Prinzregentenstr. 147;München;;81677;Deutschland
item1.X-ABADR:de
REV:2019-10-14T00:51:11Z
END:VCARD
EOF
BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//iOS 13.1.2//EN
N:Alé-D2;;;;
FN:Alé-D2
TEL;type=CELL;type=VOICE;type=pref:+49 174 456789
item1.ADR;type=HOME;type=pref:;;Prinzregentenstr. 147;München;;81677;Deutschland
item1.X-ABADR:de
REV:2019-10-14T00:51:11Z
END:VCARD
Wie wende ich das ganze an? Ich habe die Datei export.vcf. Erstelle im gleichen Verzeichnis die Datei "vcard_transform.py" 1:1 wie oben das Listing. Wie rufe ich es dann auf? Habe: vcard_transform.py << export.vcf
vcard_transform.py < export.vcf probiert
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11179
Wohnort: München
|
fileinput akzeptiert Daten, die auf dem stdin oder als Argumente übergeben werden.
python3 vcard_transform.py eingabe.vcard > ausgabe.vcard
# bzw. wenn du die vcard_transform.py ausführbar gemacht hast:
./vcard_transform.py eingabe.vcard > ausgabe.vcard Da man laut https://tools.ietf.org/html/rfc6350#section-3.2 ein \r\n am Zeilenende braucht, müsste man die print-Befehle im Skript aber noch entsprechend anpassen:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | #!/usr/bin/env python3
import fileinput
for line in fileinput.input():
line = line.rstrip()
if line.startswith('N:'):
_, _, data = line.partition(':')
name_data = data.split(';')
print(f"N:{name_data[1]};{name_data[0]};{';'.join(name_data[2:])}", end='\r\n')
change_names = TRue if all(name_data[:2]) else False
elif line.startswith('FN:'):
if change_names:
print(f"FN:{name_data[0]} {name_data[1]}", end='\r\n')
else:
print(line, end='\r\n')
else:
print(line, end='\r\n')
|
|