Schrift
[thread]13056[/thread]

RE :: Unorthodoxes Verhalten

Leser: 1


<< >> 4 Einträge, 1 Seite
Gast Gast
 2009-01-26 21:21
#118364 #118364
Hallo!

Beim Versuch, aus SQL-Statements Info zu extrahieren, bin ich auf dieses "Problem" (?) gestoßen, dessen Ursache ich mir nicht erklären kann.

Während das Ergebnis der ersten beiden Zeilen erklärbar ist (es kommt kein "UNIQUE" vor, daher ist $type leer), ...
($type, $index, $table) = "CREATE NONCLUSTERED INDEX [eaart] ON [dbo].[fvbuch]" =~ m/(UNIQUE)?.*\[(\w+)\]\s+ON\s+.*\.\[(\w+)\]/i;
print "$type, $index, $table\n"; # Liefert: ", eaart, fvbuch"

... verstehe ich nicht, warum die beiden nächsten Zeilen (jetzt mit "UNIQUE") $type ebenfalls leer (ich hätte hier "UNIQUE" erwartet) belassen.
($type, $index, $table) = "CREATE UNIQUE CLUSTERED INDEX [eaart] ON [dbo].[fvbuch]" =~ m/(UNIQUE)?.*\[(\w+)\]\s+ON\s+.*\.\[(\w+)\]/i;
print "$type, $index, $table\n"; # Liefert: ", eaart, fvbuch"

Grüße
Linuxer
 2009-01-26 21:45
#118366 #118366
User since
2006-01-27
3875 Artikel
HausmeisterIn

user image
Bitte Perl-Tags (für Perl Code) verwenden; wenigstens Code-Tags wären schön gewesen....

Das UNIQUE wird Opfer des gierigen .*, das versucht so viel wie möglich einzufangen.
Leider hilft es nicht, einfach auf das nicht gierige .*? zu wechseln, auch damit ist das UNIQUE Opfer seines Quantifiers ....


[s]Leider habe ich grade keine (schnelle) Lösung parat und mein Hirn ist nicht in Knobellaune :o([/s]

Vorm UNIQUE muss doch mindestens ein Schlüsselwort stehen, oder?
Dann könnte dieses bereits helfen:

Code (perl): (dl )
1
2
3
4
5
my ($type, $index, $table) 
  = "CREATE UNIQUE CLUSTERED INDEX [eaart] ON [dbo].[fvbuch]" 
  =~ m/\w+\s+(UNIQUE)?.*\[(\w+)\]\s+ON\s+.*\.\[(\w+)\]/i;

print "$type, $index, $table\n";


edit:
- gruppierende Klammer entfernt (relikt vom testen)
meine Beiträge: I.d.R. alle Angaben ohne Gewähr und auf Linux abgestimmt!
Die Sprache heisst Perl, nicht PERL. - Bitte Crossposts als solche kenntlich machen!
Gast Gast
 2009-01-26 22:05
#118367 #118367
Danke für die schnelle Antwort und den Lösungsansatz!

Nichtsdestotrotz ist mir nicht klar, warum die originale Lösung nicht funktioniert...

Auch wenn ich den "greedy" '*' benutze,
Code (perl): (dl )
(UNIQUE)?
kommt vor'm ersten '*', und müsste eigentlich gefunden werden. Dies kann also nur bedeuten, dass
Code (perl): (dl )
m/(UNI...
intern wie
Code (perl): (dl )
m/.*(UNI...
interpretiert wird. In diesem Falle dürfte dann aber auch die Lösung
Code (perl): (dl )
m/\s(UNIQUE)?...
eigentlich nicht funktionieren, oder?

Grüße
Linuxer
 2009-01-26 22:38
#118369 #118369
User since
2006-01-27
3875 Artikel
HausmeisterIn

user image
Hi,

das Problem liegt, so vermute ich, darin, dass links vom "(UNIQUE)?" nichts konkretes steht.
So kann ".*" sich erstmal den gesamten String links der ersten eckigen Klammer schnappen.
Da das UNIQUE nicht auftauchen muss (Quantifier: ?), ist der Teil damit erledigt.

Erst wenn links vom "(UNIQUE)?" etwas Konkretes auftritt, das "\s" beispielsweise, wird nochmal genauer hingesehen und das UNIQUE wird entdeckt und eingefangen.

Warum es mit "\s" vor der Klammerung funktioniert, kann ich Dir, ehrlich gesagt, nicht verraten.
Ich hatte eigentlich noch damit gerechnet, dass das UNIQUE damit immer noch vom ".*" verschlungen wird.
Insgesamt beschäftige ich mich zu selten intensiv mit Regex, um darauf eine passende Antwort zu haben. Ein solides Halbwissen ist vorhanden, aber alle relevanten Interna kenn ich nicht.

Ein '.' vorm "(UNIQUE)?" reicht interessanterweise nicht aus, damit UNIQUE gefunden wird.

Besser kann ich es grad nicht erklären. Vielleicht schaltet sich nochmal jemand ein, der/die sich stärker mit Regex, ihrem Debugging (es gibt sicher Module, mit denen man die Arbeitsweise betrachten kann) und ihrem internen Ablauf befasst hat. Vielleicht gibt es dann noch eine konkretere Antwort.

Mein Testskript:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/perl
# vi:ts=4 sw=4 et:
use strict;
use warnings;

my $string = 'FOO1 BAR FOO2';

my @regex = (
    qr{(BAR)?},
    qr{(BAR)?.*},
    qr{\s(BAR)?.*},
    qr{.(BAR)?.*},
);

for my $r ( @regex ) {
    my ($m) = $string =~ $r;
    printf "%8s : %s\n", ($m || 'no match'), $r;
}
meine Beiträge: I.d.R. alle Angaben ohne Gewähr und auf Linux abgestimmt!
Die Sprache heisst Perl, nicht PERL. - Bitte Crossposts als solche kenntlich machen!
<< >> 4 Einträge, 1 Seite



View all threads created 2009-01-26 21:21.