ersetze Zeichen zwischen zwei Zeichen?
Manfred
- php
Hallo,
ich bin leider ein ziemlicher Anfänger, was reguläre Ausdrücke betrifft, deswegen meine Frage hier:
Ich hab einen String, der eine Reihe von Werten enthält, alle in Anführungsstrichen gesetzt und durch Kommata getrennt.
Wenn ich jetzt die Werte in Variablen speichern möchte, kann ich ja leider nicht nach dem Komma splitten.
Ich müsste also vorher alle Kommata innerhalb der Anführungstrichem durch Punkte ersetzen.
Aus dem Bespiel
"Liste 1","40,32","20,12","12,07"
müsste also werden:
"Liste 1","40.32","20.12","12.07"
Das geht sicherlich durch reguläre Ausdrücke ... aber wie?
Lieben Dank,
Euer Manni
Hallo Manni,
das geht auch ohne RegEx:
<?php
$a='"Liste 1","40,32","20,12","12,07"';
$a=[link:http://de3.php.net/manual/de/function.explode.php@title=explode]('"',$a);
for($i=1;$i<[link:http://de3.php.net/manual/de/function.count.php@title=count]($a);$i+=2)
$a[$i]=[link:http://de3.php.net/manual/de/function.str-replace.php@title=str_replace](',','.',$a[$i]);
$a=[link:http://de3.php.net/manual/de/function.implode.php@title=implode]('"',$a);
echo $a;
?>
Gruß aus Berlin!
eddi
Hallo Eddi,
das geht auch ohne RegEx:
auch wenn ich RegEx nicht kann, ist es doch das bessere oder?
Ich würd schon ganz gerne die "elegantere" Methode verwenden.
Liebe Grüße,
Manni
Hallo Manfred.
auch wenn ich RegEx nicht kann, ist es doch das bessere oder?
Besser? Nein, finde ich nicht. Du wirst mit Regular Expressions sogar einigen Aufwand mehr haben als mit den anderen hier vorgestellten Methoden. Du möchtest eine verschachtelte Struktur analysieren, und dafür sind Regular Expressions ohne weitere "Hilfsoperationen" ziemlich ungeeignet.
Ich würd schon ganz gerne die "elegantere" Methode verwenden.
Eddis Methode ist die Kurzversion eines CVS-Parsers, der von Komma zu Komma scannt und nach dem Einlesen eines Anführungszeichens als erstem Wert alle Folgezeichen (auch Kommata!) bis zum nächsten Anführungszeichen liest. Den kannst du dir natürlich auch selber schreiben.
Was genau verstehst du aber unter "elegant"? Eddis Skript erledigt deine Aufgabe in zweieinhalb Zeilen -- Replace und Implode sind ja überflüssig, wenn du die Werte wirklich nur extrahieren und dann anderweitig weiterverarbeiten möchtest. Vielleicht nicht das, was du unter elegant verstehst, aber zumindest sehr _kurz_. ;-) Funktioniert allerdings auch nur, wenn tatsächlich _alle_ Werte in Anführungszeichen stehen.
gudn tach!
auch wenn ich RegEx nicht kann, ist es doch das bessere oder?
Besser? Nein, finde ich nicht. Du wirst mit Regular Expressions sogar einigen Aufwand mehr haben als mit den anderen hier vorgestellten Methoden.
pauschal kann man meiner erfahrung nach schlecht die geschwindigkeit von sowas beurteilen.
ein gegenbeispiel aus juengster zeit: </archiv/2006/4/t127277/#m821481>
Du möchtest eine verschachtelte Struktur analysieren
naja, verschachtelungstiefe=1. ist jetzt noch nicht soo verschachtelt.
, und dafür sind Regular Expressions ohne weitere "Hilfsoperationen" ziemlich ungeeignet.
1. nicht zwangslaeufig. mit look-aheads und -behinds geht da so einiges.
2. und was spricht gegen solche hilfsoperationen?
prost
seth
'Nabend seth.
pauschal kann man meiner erfahrung nach schlecht die geschwindigkeit von sowas beurteilen.
Hab ich auch gar nicht. Ich rede lediglich vom Aufwand beim Programmieren dieser Geschichte. Um Performance (gemessen in Abarbeitungszeit des Skripts o.ä.) ging es mir überhaupt nicht.
Du möchtest eine verschachtelte Struktur analysieren
naja, verschachtelungstiefe=1. ist jetzt noch nicht soo verschachtelt.
Richtig, aber trotzdem schon mehr Aufwand für RegExps (z.B. mit Assertions, wie du schon selber sagst). Ob die es "eleganter" machen? Ich weiß ja nicht... Jedenfalls schwerer für Manfred, der eigener Aussage nach bisher gar nichts mit Regular Expressions zu tun hatte.
Daß sie in diesem konkreten Fall umfangreicher werden als in deinem Beispiellink. Eingeschlossen werden die Werte nämlich _nicht_ durch zwei unterschiedliche Zeichen (< und >), sondern eben nur die Anführungsstriche. Das verkompliziert die Sache in meinen Augen zumindest so sehr, daß es auch kein großer Schritt mehr zu einem selbstgeschrieben CSV-Parser wäre -- auch wenn dieser sicher ein paar mehr Zeilen Code hätte. ;-)
Spricht in deinen Augen etwas gegen Eddis oder Toms Lösung?
Hallo seth.
Mal abgesehen davon, daß ich vorhin nicht Tom sondern dedlfix meinte (bin wohl im falschen Tab gelandet), stelle ich gerade fest, daß das hier ...
Das verkompliziert die Sache in meinen Augen zumindest so sehr, daß es auch kein großer Schritt mehr zu einem selbstgeschrieben CSV-Parser wäre
... zugegebenermaßen etwas übetrieben war. Ich hatte mir die Sache etwas komplizierter vorgestellt als sie eigentlich ist. Hatte auch deinen anderen Beitrag weiter oben vorhin noch nicht entdeckt.
Also: Kommando zurück!
Ich hau mich jetzt aufs Ohr. Wird ja offensichtlich langsam Zeit. ;-)
Tachchen,
auch wenn ich RegEx nicht kann, ist es doch das bessere oder?
Besser? Nein, finde ich nicht. Du wirst mit Regular Expressions sogar einigen Aufwand mehr haben als mit den anderen hier vorgestellten Methoden.
pauschal kann man meiner erfahrung nach schlecht die geschwindigkeit von sowas beurteilen.
ein gegenbeispiel aus juengster zeit: </archiv/2006/4/t127277/#m821481>
da kann ich Dir aber pauschalisieren, daß Du mehr Probleme und mehr Zeitaufwand mit RegEx beim erstellen/warten hast, als mit einer Prozedur Deiner eigenen Sprache. :)
Gruß aus Berlin!
eddi
echo $begrüßung;
Ich hab einen String, der eine Reihe von Werten enthält, alle in Anführungsstrichen gesetzt und durch Kommata getrennt.
Wenn ich jetzt die Werte in Variablen speichern möchte, kann ich ja leider nicht nach dem Komma splitten.
Kommt der String vielleicht aus einer Datei? Dann wäre fgetcsv() eine bessere Methode, diese auszulesen.
echo "$verabschiedung $name";
Hallo,
Kommt der String vielleicht aus einer Datei? Dann wäre fgetcsv() eine bessere Methode, diese auszulesen.
Der String kommt zwar aus einer Datei, aber diese enthält (leider) nicht nur csv-Code. Ich müsste also, um die Funktion zu verwenden, durch die Datei parsen, den CSV-Bereich auslesen und erst in eine Datei speichern, damit ich diese dann wieder mit fgetcsv auslesen kann.
Das ist noch umständlicher ;-))
Liebe Grüße
echo $begrüßung;
Kommt der String vielleicht aus einer Datei? Dann wäre fgetcsv() eine bessere Methode, diese auszulesen.
Der String kommt zwar aus einer Datei, aber diese enthält (leider) nicht nur csv-Code. Ich müsste also, um die Funktion zu verwenden, durch die Datei parsen, den CSV-Bereich auslesen und erst in eine Datei speichern, damit ich diese dann wieder mit fgetcsv auslesen kann.
Das ist noch umständlicher ;-))
Ja, aber nur, wenn du das _so_ machst :-)
Du kannst auch mit den "normalen" Dateilesefunktionen - z.B. mit fgets() - zuerst den Nicht-CSV-Teil lesen. Dann liest du einfach mit dem selben Dateihandle aber mit fgetcsv() weiter bis der CSV-Teil endet und dann gehts wieder mit fgets() weiter ...
echo "$verabschiedung $name";
gudn tach!
Ich müsste also vorher alle Kommata innerhalb der Anführungstrichem durch Punkte ersetzen.
Aus dem Bespiel
"Liste 1","40,32","20,12","12,07"
müsste also werden:
"Liste 1","40.32","20.12","12.07"Das geht sicherlich durch reguläre Ausdrücke ... aber wie?
mit preg_replace('/(".*?")/e', 'strtr("$1", ",", ".")', $str)
ginge es bswp., allerdings _muss_ dann ein anfuehrungszeichen immer einen begrenzer darstellen. sowas wie "foo"bar"" waere also nicht mehr erlaubt. je nach anwendungsfall waere dir damit schon geholfen.
links aus dem php-manual: strtr, preg_replace, pattern modifiers.
je nach dem, wie die files aussehen, aus denen du den kram einliest, ist der weg ueber die von dedlfix angesprochene methode evtl. effizienter.
prost
seth
Hallo,
for($j=0;$j<100000;$j++){
$a=explode('"','"Liste 1","40,32","20,12","12,07","Liste 1","40,32","20,12","12,07","Liste 1","40,32","20,12","12,07"');
for($i=1;$i<count($a);$i+=2)
$a[$i]=str_replace(',','.',$a[$i]);
$a=implode('"',$a);
}
$ time env -i ./x.php
real 0m4.170s
user 0m4.132s
sys 0m0.008s
for($i=0;$i<100000;$i++)
$a=preg_replace('/(".*?")/e', 'strtr("$1", ",", ".")', '"Liste 1","40,32","20,12","12,07","Liste 1","40,32","20,12","12,07","Liste 1","40,32","20,12","12,07"');
$ time env -i ./y.php
real 0m17.449s
user 0m17.405s
sys 0m0.000s
Testumgebung:
AMD Athlon(tm) XP 1800+
RAM 759472 kB
OS: GNU/Linux (gentoo) 2.6.16.5
PHP: 5.1.3-dev CLI
man sollte nicht verallgemeinern - sicher, aber dies ist mal wieder einer der doch recht typischen Ergebnisse, die mich auch weiterhin davon abhalten werden, diesen Mist einzusetzen.
Gruß aus Berlin!
eddi