Schrift
[thread]7900[/thread]

Zeichen in RegEx darf nicht zwischen <> stehen (Seite 3)

Leser: 2


<< |< 1 2 3 >| >> 27 Einträge, 3 Seiten
Crian
 2006-04-20 15:55
#65030 #65030
User since
2003-08-04
5873 Artikel
ModeratorIn
[Homepage]
user image
Im Zweifelsfall in zwei Stufen ersetzen, erstmal in kryptische Platzhalterung, etwa QQQFARBEANFANG=#00ff00QQQ ... QQQFARBEENDEQQQ (oder was auch immer) und ganz am Ende dann den eigentlich Code eintragen statt dieser Platzhalter.

Trotzdem ist die Verwendung des Moduls bestimmt der robustere Weg.
s--Pevna-;s.([a-z]).chr((ord($1)-84)%26+97).gee; s^([A-Z])^chr((ord($1)-52)%26+65)^gee;print;

use strict; use warnings; Link zu meiner Perlseite
Matze
 2006-04-20 18:51
#65031 #65031
User since
2005-08-29
222 Artikel
BenutzerIn
[Homepage] [default_avatar]
@Crian: Ich habe mir erstmal das Modul genauer angesehen, und dann festgestellt das es nicht so gut dafür geeignet ist.
Und, ich habe meinen Vater gefragt, er hat mit das selbe gesagt wie du!
Erst Zeichenkette davor und danach, dann am Ende ersetzen, ich habe es ein bisschen erweitert, und so siehts jetzt aus:
Code: (dl )
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#!/usr/bin/perl -w
#

# Module einbinden:

use strict;
use HTML::Entities;

# Dateinamen, Trenner holen:

my $file = shift || die("USAGE: test.pl filename outfile sep");
my $out = shift || "a.html";
my $s = shift || chr(1);

# @func festlegen:

my @func  =  qw(print chomp chop chr crypt hex index lc lcfirst length oct ord pack reverse rindex
sprintf substr uc ucfirst pos quotemeta split study abs atan2 cos exp hex int log
oct rand sin sqrt srand pop push shift splice unshift grep join map reverse sort
unpack delete each exists keys values binmode close closedir dbmclose dbmopen die
eof fileno flock format getc print printf read readdir rewinddir seek seekdir select
syscall sysread sysseek syswrite tell telldir truncate warn write pack read syscall
sysread syswrite unpack vec -X chdir chmod chown chroot fcntl glob ioctl link lstat
mkdir open opendir readlink rename rmdir stat symlink sysopen umask unlink utime
caller continue die do dump eval exit goto last next redo return sub wantarray defined
dump eval formline local my our reset scalar undef wantarray alarm exec fork getpgrp
getppid getpriority kill pipe setpgrp setpriority sleep system times wait waitpid do
import no package require use bless package ref tie tied untie use
accept bind connect getpeername getsockname getsockopt listen recv send setsockopt
shutdown socket socketpair msgctl msgget msgrcv msgsnd semctl semget semop shmctl
shmget shmread shmwrite endgrent endhostent endnetent endpwent getgrent getgrgid
getgrnam getlogin getpwent getpwnam getpwuid setgrent setpwent endprotoent endservent
gethostbyaddr gethostbyname gethostent getnetbyaddr getnetbyname getnetent
getprotobyname getprotobynumber getprotoent getservbyname getservbyport getservent
sethostent setnetent setprotoent setservent gmtime localtime time times);

# Farben holen:

my %shl;

open IN, "shl.ini";
 while (my$line = <IN>) {
   chomp $line;

   my ($key,$val) = split "=",$line;
   $shl{$key} = $val;
 }
close IN;

# Datei in $data einlesen.

my $data;

open IN, "$file" or die "USAGE: test.pl filename outfile sep";
 while (my$line = <IN>) {
   $data .= "$line";
 }
close IN;

# $data bearbeiten:

$data =~ s/(__.+__)$/${s}M1$1${s}M2/gim;
$data =~ s/(\d+)/${s}Z1$1${s}Z2/gi;
$data =~ s/([\\\/\$\@\¤\%\^\}\]\)\(\[\{\&\;]+)/${s}S1$1${s}S2/gi;
foreach my$func (@func) {
 $data =~ s/($func)/${s}F1$1${s}F2/gi;
}
$data =~ s/\"(.*)\"/${s}W1\"$1\"${s}W2/gi;
$data =~ s/(((s|tr|y)\/.*)?\/.*\/[gimsoecx]*)/${s}R1$1${s}R2/gi;
$data =~ s/(#.*)$/${s}C1$1${s}C2/gim;

$data = encode_entities($data,"<>");

$data =~ s/\n/\n<br>/g;
$data =~ s/${s}Z1/<font color=\"$shl{int}\">/g;
$data =~ s/${s}S1/<font color=\"$shl{special}\">/g;
$data =~ s/${s}W1/<font color=\"$shl{string}\">/g;
$data =~ s/${s}F1/<font color=\"$shl{func}\">/g;
$data =~ s/${s}C1/<font color=\"$shl{comment}\">/g;
$data =~ s/${s}M1/<font color=\"$shl{section}\">/g;
$data =~ s/${s}R1/<font color=\"$shl{regex}\">/g;
$data =~ s/${s}Z2/<\/font>/g;
$data =~ s/${s}S2/<\/font>/g;
$data =~ s/${s}W2/<\/font>/g;
$data =~ s/${s}F2/<\/font>/g;
$data =~ s/${s}C2/<\/font>/g;
$data =~ s/${s}M2/<\/font>/g;
$data =~ s/${s}R2/<\/font>/g;

$data = "<font color=\"$shl{undef}\"><pre>$data<\/pre><\/font>";

# Daten rausschreiben.

open OUT, ">$out";
 print OUT $data;
close OUT;


Allerdings gibt es noch Probleme mit section.
Er ersetzt die chr(1)&☺ noch nicht.
Und regex werden noch nicht vollständig eingefärbt, ich werds mir nochmal ansehen, bestimmt ist es nur ein kleiner Fehler.

Sonst finde ich das Ergebnis schon ganz gut.

MfG. Matze
Mit freundlichen Grüßen: Matze
renee
 2006-04-20 19:54
#65032 #65032
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
[quote=Matze,20.04.2006, 13:25]Nein, eigentlich nicht, aber es gibt ja auch schon Probleme wenn ich nicht nur Zahlen rot färben,
sondern auch andere Elemente wie ein bestimmtes Wort grün färben möchte.

Am Ende soll es eine HTML Datei sein.

Und nach dem rot färben, gibt es dann auch schon <font>-Tags.
Wenn dann das Wort das grün werden soll 'color' heißt, habe ich ein Problem.

Allerdings merke ich gerade das es mit HTML::Parser auch nicht so ohne weiteres geht, wenn man mehrere Elemente färben möchte.
Ich werde mir mal den eg/ Ordner runterladen, vielleicht ist ein gutes Beispiel für genau das was ich brauche mit dabei.

MfG. Matze[/quote]
Beschreib mal genauer was Du meinst, vielleicht kann ich Dir bei CPAN:HTML::Parser etwas helfen.
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
Matze
 2006-04-20 20:59
#65033 #65033
User since
2005-08-29
222 Artikel
BenutzerIn
[Homepage] [default_avatar]
OK, ohne HTML::Parser läuft es jetzt.
Also, eigentlich wollte ich am Anfang nur Wissen ob man in einer RegularExpression irgendwie sagen kann, dass etwas NICHT drin stehen darf.
Allerdings sollte das auch bei subsitute funktionieren und bei mehrzeiligen Strings.

Nicht so wie $' und $`.(Zumindest hat es bei mir nicht sehr gut mit ihnen funktioniert)

Allerdings habe ich mir dann gedacht, dass ich daraus auch irgendwas nützliches machen könnte, also hab ich das mit dem färben dazu gebracht.
Jetzt sollen Textabschnitte in "" in einer bestimmten Farbe gefärbt werden, Zahlen sollen in einer bestimmten Farbe gefärbt werden, Kommentare, Sektionen(ich weiß nicht wie man _ _DATA_ _, _ _END_ _, usw. nennt), RegularExpressions, Perl Standart Funktionen und Sonderzeichen.

Die Farben bestimme ich jetzt in einer Datei.

Bei HTML::Parser hatte ich das Problem, dass ich, wenn ich text_h => [\&sub,"text"] handle, in der sub text_h genau das selbe machen müsste asl wenn ich HTML::Parser nicht verwende, bis darauf, dass ich keine HTML-Tags mit hinein bekomme.
Doch die baue ich ja sowieso mit rein, wenn ich mehreres mit dem <font>-Tag färben möchte.
Auf die Art, wie ich es jetzt mache, könnte ich es auch mit HTML::Parser machen, aber es wäre keine Verbesserung.

Aber vielleicht kann ich HTML::Parser auch einfach nicht anwenden.
Habe dem Wiki-Artikel allerdings nicht mehr entnommen, als dass man HTML-Tags wunderbar damit handlen kann.

MfG. Matze
Mit freundlichen Grüßen: Matze
sid burn
 2006-04-20 22:07
#65034 #65034
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Quote
Also, eigentlich wollte ich am Anfang nur Wissen ob man in einer RegularExpression irgendwie sagen kann, dass etwas NICHT drin stehen darf.

Wenn es ein einzelnes Zeichen ist dann kannst du eine negierte Zeichenklasse dafür verwenden:

[^abc]

Das matcht auf jedes Zeichen das nicht a,b oder c ist. Soll mehr als ein Zeichen nicht erkannt werden, ein String etc. empfiehlt sich ein Negatives Lookahead.

hallo(?!, welt)

Das Bedeutet das nach einem hallo nicht die Zeichenkette ", welt" folgen darf. Allerdings gibt es bei Lookaaround Konstrukt noch einiges mehr zu beachten. Sie selber passen immer nur auf Positionen, nehmen aber nie Text ein.

Code: (dl )
1
2
$string = "Hallo Welt wie geht es dir?";
$string =~ s/Hallo(?= Welt)//;


Das würde z.B. nur das "Hallo" durch nichts ersetzen. Zwar wird überprüft ob nach dem Hallo ein " Welt" folgt, allerdings wird dieses Welt nicht erfasst. Nur "Hallo" zählt als match auf dem die Substitution angewendet wird.

(Genauer: Nach "Hallo" steht die Regex Maschiene auf der Position zwischen "o" und dem Leerzeichen. Es wird überprüft ob von dieser Position aus gesehen das " Welt" vorkommt. Ist dies der Fall matcht die Position, da dies die komplette Regex ist, ist das matching vorbei, und eine ersetzung findet statt. Das Lokkahed Konstrukt hat aber letztlich nur auf eine bestimmte Position geprüft und kein Text erkannt. Würde danach kein " Welt" kommen würde die Position nicht stimmen, und die Regex Maschine würde wieder nach der Zeichenfolge "Hallo" suchen und ob die Position danach auch matcht. Nur wenn das der Fall ist findet eine Substitution statt. Vielleicht ist die genaue Beschreibung etwas Verständlicher.)



Ansonsten ist es in deinem Fall ja etwas schwerer zu erkennen was wirklich gemeint ist. Du sagst zwischen spitzen Klammern darf es nicht vorkommen. Was du aber denke ich wirklich meinst ist das es nicht innerhalb eines HTML Tags eretzt werden darf. Deine Aussage ist da nicht genau genug, und das sind ziemlich große Unterschiede. Zwischen spitzen Klammern wäre auch folgendes:

Code: (dl )
print "<", 1234, ">";


Was aber sicherlich kein HTML Tag ist.


Quote
Allerdings sollte das auch bei subsitute funktionieren und bei mehrzeiligen Strings.

Deine Regex erkennt das selbe, egal ob nun Substiution oder ein Match.

Weiterhin wenn du keins von den folgenden drei Zeichen benutzt: ^$. dann ist es volkommen egal ob der String aus mehreren Logischen Zeilen besteht oder nicht. Deine Regex wird immer auf den ganzen String angewendet.

Der Punkt passt auf alles, auser dem Newline Zeichen. Das heißt wenn du den Punkt in deiner Regex benutzt, und du möchtest das er über mehrere Logische Zeilen hinweg geht, dann musst du die /s Option benutzen. Aber nur wenn du den Punkt benutzt. Wenn du ihn nicht benutzt hat dies kein Effekt auf den String oder die Regex.

Ansonsten passt ^ und $ Stadardmäßig auf String Anfang und String Ende. (Nicht Zeilenanfang und Zeilenende). Manchmal ist es aber gewünscht das du logische Zeilen erkennst, wenn das gewünscht ist musst du die Option /m benutzen. Dadurch passt das ^ kurz nach einem Newline Zeichen (oder String Anfang), und $ kurz vor einem Newline Zeichen (oder String Ende). Die Zeilen werden dadurch also Simuliert.

Ansonsten ist es deiner Regex ziemlich egal ob dein String nun mehrere logische Zeilen besitzt oder nicht. Es wird immer der String bearbeitet, keine Zeilen.

Quote
Nicht so wie $' und $`.(Zumindest hat es bei mir nicht sehr gut mit ihnen funktioniert)

Was hast du den damit ausprobiert? Also erstens muss man hier kritisch sagen, dass du diese Variablen nicht verwenden solltest. Das hat mit PErformance zu tun, den die geht damit drastisch in den keller. Vor allem wenn du mehrere Module und viele Regexe benutzt.

Ansonsten erkennen diese Zeichen nach einem Match was vor dem Match und nach einem Match stand. Es gibt noch eine dritte Variable $& die erkennt genau das, auf was die Regex gematcht hat.

Sagen wir du hast folgenden String "Hallo 123 Welt". Und deine Regex schaut folgendermaßen aus \d+. Dann sind die Variablen nach deinem match folgendermaßen gefüllt.
Code: (dl )
1
2
3
$' = "Hallo "
$& = "123"
$` = " Welt"

Allerdings werden diese Variablen nicht nur nach dem Match gefüllt, sondern nach absolut jedem Zeichen das deine Regex neu erkennt, für jeden Backtracking Versuch etc. Und wenn du diese Variablen einmal benutzt wird dieses verhalten gleich für absolut jede Regex in absolut jedem Modul im komplett Programm aktiviert. Das kostet viel Performance.


Quote
Jetzt sollen Textabschnitte in "" in einer bestimmten Farbe gefärbt werden, Zahlen sollen in einer bestimmten Farbe gefärbt werden, Kommentare, Sektionen

Hättest du von Anfang an gesagt das es sich hier nur um Werte innerhalb von Anführungszeichen geht dann wäre das alles deutlich einfacher gewesen....

Vielleicht solltest nochmal genau beschreiben was du überhaupt genau haben möchtest, und vielleicht auch mal direkt deine Beispieldatei Posten (sofern das geht) damit man direkt damit arbeiten kann, oder generell BEschreiben was du da überhaupt für eine Datei hast.

Wenn man Reguläre Ausdrücke schreibt dann muss man zu 100% Wissen wie die Daten aussehen, und alle Möglichen Fälle abdecken die Auftreten könnten, wenn man das nicht beachtet geht es früher oder später irgendwann in die Hose.


Wenn eine Ersetzung nur Innerhlab von Anführungszeichen stattfindet dann ist das shcon ein guter Punkt der das ganze einfacher macht, das ganze reicht aber trotzdem nicht aus. Welche Sprache benutzt du? Was ist wenn du ein Anführungszeichen innerhlab eines Strings schreiben möchtest? Wird das dann z.B. mit einem Backslash davor escaped? [\"] Wenn es sich um einen String handelt, ist es dann die einzige Möglichkeit wie ein String definiert wird? In den meisten Sprachen gibt es auch immer ein einzelnes Hochkomma, das müsste auch Berücksichtigt werden. (Bei Perl gibt es sogar noch die q und qq Oberatoren mit Variablen Zeichen, darüber darf man gar nicht erst nachdenken...) Gibt es Kommentare? Wenn ja wie sehen diese aus? Dort möchtest du sicherlich auch keine Sachen ersetzen. Solche Sachen muss man Berücksichtigen beim Schreiben einer Regex.

Auch wenn man zu Anfang denkt das sowas wie Ersetzen zwischen Anführungszeichen recht einfach geht.


Wenn du keine genauen Informationen lieferst geht sowas schlecht. Allerdings hängt es immer auch davon ab wofür du soetwas benötigst. Wenn es eine einmalige Aktion ist, kannst du auch eine unpräzise Möglichkeit nehmen, und danach nochmal über die Datei drüber schauen, wenn du irgendetwas automatisieren möchtest, und auf Korrektheit ankommt, dann geht sowas nicht.\n\n

<!--EDIT|sid burn|1145558717-->
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
renee
 2006-04-20 23:01
#65035 #65035
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
CPAN:HTML::Parser macht genau das, was der Name verrät: HTML parsen. Was Du mit dem Text machen möchtest, kann das Modul nicht wissen.

CPAN:HTML::Parser ist ideal für solche Sachen wie die Zahlen rot färben, aber nicht die Zahlen innerhalb eines HTML-Tags!

Du scheinst ein Programm für Syntaxhighlighting schreiben zu wollen. Hast Du Dir schonmal CPAN:PPI::HTML angeschaut??
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
Matze
 2006-04-21 00:01
#65036 #65036
User since
2005-08-29
222 Artikel
BenutzerIn
[Homepage] [default_avatar]
Nein, so weit sollte es nicht gehen.
PPI::HTML ist sicher ganz interessant, aber ich wollte es nur mal ausprobieren, mit RegularExpressions.
Und es funktioniert ja jetzt auch!

Trotzdem danke!

MfG. Matze
Mit freundlichen Grüßen: Matze
<< |< 1 2 3 >| >> 27 Einträge, 3 Seiten



View all threads created 2006-04-18 11:40.