Avatar billede tbm_iceman Nybegynder
20. juni 2004 - 21:28 Der er 42 kommentarer og
1 løsning

Parse data ved hjælp af RegExp

Jeg har en html side med ca. 200 rækker i en tabel...
Jeg skal bruge det data der i tabellen og så tænkte jeg på at parse det med RegExp og så bare tage dataen derfra? Er det muligt og i så fald hvordan ville man lave en streng der kan gøre følgende...

Her er HTML'en:
<tr align="center"><td align="right" valign=top class="small">[Data-1]</td><td nowrap valign=top class="small">[Data-2]</td><td valign=top class="small">[Data-3]</td><td valign=top align="right" class="small" nowrap>[Data-4]</td><td>&nbsp;</td><td class="small" align="left" valign=top><a href="[Data-5]">[Data-6]</a></td></tr>

Alle rækkerne ser således ud... Jeg skal bruge de 6 data felter ... Hvordan gøres det lettest?
Avatar billede roenving Novice
20. juni 2004 - 21:40 #1
Her er det vigtigste, du skal selvfølgelig splitte din tabel, f.eks. med '</tr>' og så skal du bagefter køre replacen på alle delstrenge, og til sidst splitte dine data for den delestreng, du vælger i replace-linjen (her har jeg brugt et komme, men du skal vælge en, du ved ikke forekommer i dine data !-)

<script language="javascript" type="text/javascript">
var x = '<tr align="center"><td align="right" valign=top class="small">[Data-1]</td><td nowrap valign=top class="small">[Data-2]</td><td valign=top class="small">[Data-3]</td><td valign=top align="right" class="small" nowrap>[Data-4]</td><td>&nbsp;</td><td class="small" align="left" valign=top><a href="[Data-5]">[Data-6]</a></td></tr>'
var reg = /.*<td[^>]*>([^<]*).*<td[^>]*>([^<]*).*<td[^>]*>([^<]*).*<td[^>]*>([^<]*).*<td[^>]*>.*<td[^>]*><a href=\"([^"]*)">([^<]*).*/gi;
alert(x.replace(reg,"$1,$2,$3,$4,$5,$6"));
</script>
Avatar billede tbm_iceman Nybegynder
20. juni 2004 - 21:43 #2
hmm... hvordan vil det se ud hvis man gjore det i ASP istedet? Altså RegExp delen burde være det samme... men tænkte på hvordan man lige får den til at gøre det de 200 gange...
Avatar billede roenving Novice
20. juni 2004 - 21:48 #3
Brug split-funktionen til at dele dine data op i et array, løb arrayet igennem, udfør en replace overfor de enkelte værdier, og lav så en split på værdierne tilsidst, og du burde kunne lave et to-dimensionelt array ...
Avatar billede tbm_iceman Nybegynder
20. juni 2004 - 21:59 #4
hmm har lidt problemer med at komme forbi tegnet " i min RegExp.Pattern ... hvordan gør man lige det lettest i ASP?
Avatar billede roenving Novice
20. juni 2004 - 22:01 #5
Du er i vbscript, så skal den fordobles i en streng:

a href=""([^""]*)"">([^<]*).*/gi;
Avatar billede tbm_iceman Nybegynder
20. juni 2004 - 22:22 #6
hmm... der er noget galt med mit Pattern, for det finder ingen matches...

Her er min funktion:

Function DataParser(strText)
    Dim RegExp
    Set RegExp = New RegExp
    RegExp.IgnoreCase = True
    RegExp.Global = True

    RegExp.Pattern = "/.*<td[^>]*>([^<]*).*<td[^>]*>([^<]*).*<td[^>]*>([^<]*).*<td[^>]*>([^<]*).*<td[^>]*>.*<td[^>]*><a href=\""([^""]*)"">([^<]*).*/gi;"
    strText = RegExp.Replace(strText, "$1$2$3$4$5$6" & Chr(13))
   
    Set RegExp = Nothing
    DataParser = strText
End Function
Avatar billede roenving Novice
20. juni 2004 - 22:39 #7
Du skal selvfølgelig fjerne javascript-sporene, det glemte jeg lige:

RegExp.Pattern = ".*<td[^>]*>([^<]*).*<td[^>]*>([^<]*).*<td[^>]*>([^<]*).*<td[^>]*>([^<]*).*<td[^>]*>.*<td[^>]*><a href=""([^""]*)"">([^<]*).*"
Avatar billede tbm_iceman Nybegynder
21. juni 2004 - 01:10 #8
yeps... nu virker det...
mange tak.


Så hvis du lige smider et svar!
Avatar billede roenving Novice
21. juni 2004 - 01:12 #9
Velbekomme '-)
Avatar billede roenving Novice
21. juni 2004 - 01:16 #10
-- og tak for point ;~}
Avatar billede tbm_iceman Nybegynder
21. juni 2004 - 01:20 #11
Har lige et sidste spørgsmål kan det passe at RegExp er MEGET langsom... Det er fordi jeg har skrevet 2 parserer... den ene med RegExp den anden er hardcoded hvor den fjerner alt html indtil der kun er dataen tilbage... kan det passe at den er 4-5 gange langsommere?
Avatar billede roenving Novice
21. juni 2004 - 01:26 #12
Normalt er regexp hurtigere, specielt hvis opgaverne bliver lidt komplicerede, men du opretter jo regexp'en på ny ved hvert gennemløb, jeg vil tro, at det flytter ret voldsomt på afviklingstiden, hvis du bare opretter den en gang og så hiver data ud med den samme regexp-instans hver gang !-)

-- og jeg overvejede også simpelthen at fjerne alle tags, for umiddelbart ville det jo være lettere, men det satte linket jo en stopper for ...
Avatar billede tbm_iceman Nybegynder
21. juni 2004 - 02:17 #13
hmm... så må der være noget galt med Pattern igen ... nu har jeg prøvet flere ting... men hvis jeg laver en string med fx. 2 af dem i så finder den kun den ene.. hvorfor?
men hvis jeg gør det mega simpelt som fx. sætter den til at finde "is" i denne streng "IS1 is2 IS3 is4" virker det fint...

Ved du hvad der er galt?
Avatar billede roenving Novice
21. juni 2004 - 02:22 #14
Hvor får du dine tabeldata fra ?-)

For da jeg prøvede måtte jeg fjerne linjeskift i strengen, fordi jeg hentede det som innerHTML, og der var den IE-maskine, der sidder i min webwriter, så venlig at indsætte et utal af linjeskift ...

-- og selv om .* burde betyde et hvilkensomhelst antal af et hvilkensomhelst tegn, måtte jeg altså først fjerne linjeskiftene med replace(/(\r\n|\n|\r)/g,"") -- igen javascript !-)
Avatar billede tbm_iceman Nybegynder
21. juni 2004 - 02:24 #15
hehe.... det prøver jeg lige... har nemlig allerede en funktion der gør det.. brb in 2 min
Avatar billede tbm_iceman Nybegynder
21. juni 2004 - 02:29 #16
det er stadig det samme... har fjernet dem med en replace på Chr(9) - 10 - 11 - 12 - 13 ... hvilket svare til det samme som du skriver i JS... men det virker stadig ikke...

men har fundet ud af at den tror at HELE strengen som er ca 27800 char lang er et match.... men det burde den da ikke kunne med det pattern du har sat?
Avatar billede roenving Novice
21. juni 2004 - 02:31 #17
Splitter du strengen først ?-)

Prøv først at lave den split på </tr> !-)
Avatar billede tbm_iceman Nybegynder
21. juni 2004 - 02:35 #18
ja men det kan jeg sagtens... det var den måde jeg gjore det på før...
men så vil den jo kun finde en pr element i arrayen dvs.. en pr. </tr> ville gerne lave denne funktion her...

    RegExp.Pattern = "<td[^>]*>([^<]*).*<td[^>]*>([^<]*).*<td[^>]*>([^<]*).*<td[^>]*>([^<]*).*<td[^>]*>.*<td[^>]*><a href=""([^""]*)"">([^<]*)"
    Set Matches = RegExp.Execute(RetStr)    ' Execute search.
    For Each Match in Matches                ' Iterate Matches collection.
        'Gør noget her!!!
    Next

men så er det jeg kun får et match... :(

før der lavede jeg bare et array inden i funktionen og satten den til at scanne hvert ellement i arrayet for mit pattern..
Avatar billede roenving Novice
21. juni 2004 - 02:38 #19
Ah, du vil prøve at få executen til at danne dit array ...

Hrm, hrm ...
Avatar billede tbm_iceman Nybegynder
21. juni 2004 - 02:39 #20
ja og det er muligt... da jeg prøvede med de simple ovenfor med "is" men ikke med dit pattern... fatter det ikke...
Avatar billede roenving Novice
21. juni 2004 - 02:47 #21
Prøv med dette pattern:

RegExp.Pattern = "\s+<td[^>]*>([^<]*).*\s+<td[^>]*>([^<]*).*\s+<td[^>]*>([^<]*).*\s+<td[^>]*>([^<]*).*\s+<td[^>]*>.*\s+<td[^>]*><a href=""([^""]*)"">([^<]*).*<\/tr>"
Avatar billede tbm_iceman Nybegynder
21. juni 2004 - 02:49 #22
ingen matches...

men tror det har noget at gøre med () ... måske er det fordi man ikke kan bruge dem i et Matches object...
Avatar billede roenving Novice
21. juni 2004 - 02:49 #23
-- den skal forøvrigt eksekveres uden at fjerne linjeskift (da \s har brug for dem !-)

-- og hastigheden på udregningen faldt hos mig fra ca. 15 sekunder til ca. 0,06 sekunder !o]
Avatar billede tbm_iceman Nybegynder
21. juni 2004 - 02:51 #24
det var heller ikke det....

Prøvede lige med:
RegExp.Pattern = "<td[^>]*>([^<]*)"

der fandt den 432 matches...

Argh det her giver mig sure løg...
Avatar billede roenving Novice
21. juni 2004 - 02:55 #25
Jeg har testet den med dette java script:

<script language="javascript" type="text/javascript">
function test(){
  var tim = new Date();
  var x = document.getElementById('datadiv').firstChild.firstChild.innerHTML;
  var nytim = new Date();
  var reg = /\s+<td[^>]*>([^<]*).*\s+<td[^>]*>([^<]*).*\s+<td[^>]*>([^<]*).*\s+<td[^>]*>([^<]*).*\s+<td[^>]*>.*\s+<td[^>]*><a href="([^"]*)">([^<]*).*<\/tr>/gi;
  x = x.match(reg)
  var data = new Array(x.length);
  for(i=0;x.length>i;i++){
    data[i] = x[i].replace(reg,"$1,$2,$3,$4,$5,$6").split(",");
  }
  var nytim = new Date();
  alert(data.length+"\n"+data+"\n"+(nytim.getTime()-tim.getTime())/1000);
}
</script>
<body onload="test()">

<div id="datadiv">
<table>
<tr align="center"><td align="right" valign=top class="small">[Data-1]</td><td nowrap valign=top class="small">[Data-2]</td><td valign=top class="small">[Data-3]</td><td valign=top align="right" class="small" nowrap>[Data-4]</td><td>&nbsp;</td><td class="small" align="left" valign=top><a href="[Data-5]">[Data-6]</a></td></tr>
...
</table>
</div>

-- der parser den stadset på 0.063 sekunder ...
Avatar billede tbm_iceman Nybegynder
21. juni 2004 - 02:55 #26
har fundet problemet nu.... håber så bare du kan udbedre det... :P

RegExp.Pattern = "<td[^>]*>([^<]*).*<td[^>]*>"

den vil ikke godtage kombinationen '.*' så snart den optræder i pattern strengen fejler den..
Avatar billede tbm_iceman Nybegynder
21. juni 2004 - 02:57 #27
eller det vil sige den fejler ikke... den finder bare kun et match!

hmm.. ville gerne kunne bruge dit JS.. men det skal desvære være serverside mit script.
Avatar billede roenving Novice
21. juni 2004 - 02:58 #28
Jah, der er vist en af forskellene, jeg har set den med et spørgsmålstegn på adskillige gange .*?

-- men den har jeg ikke fundet forklaring på i de dokumentationer, jeg er stødt ind i (som naturligt nok har haft javascript som udgangspunkt !-)
Avatar billede roenving Novice
21. juni 2004 - 02:58 #29
Du kan da gost køre Jscript i asp ...
Avatar billede tbm_iceman Nybegynder
21. juni 2004 - 03:01 #30
ja det ville jeg godt.... men skal have dem jongleret over i ASP som variabler... desuden er jeg meget rusten i Jscript...

men det med '?' fik det til at virke... :) så nu virker det 100% og det er satanme hurtigt... :)
Avatar billede roenving Novice
21. juni 2004 - 03:04 #31
Phew ...

-- muy bueno !-)
Avatar billede tbm_iceman Nybegynder
21. juni 2004 - 03:11 #32
hmm... kan squ ikke lige hitte ud af hvordan jeg skal hive Date1-6 ud af den når det ligger i et match object... noget du kender noget til?
Avatar billede roenving Novice
21. juni 2004 - 03:14 #33
-- og, ja, så er det zq hurtigt, en lille stribe tests af ovenstående javascript gav ca. 2 ud af 3 gange 0.062 eller 0.063 s., resten af gangene gav det 0.046 eller 0.047 s. altså 0.04 til 0.05 millisekunder pr. variabel !-)

Nej, der kommer jeg til kort med vbscripts måde at behandle detaljer i array; som du vil kunne se, har jeg replacet og splittet det bagefter ...
Avatar billede tbm_iceman Nybegynder
21. juni 2004 - 03:15 #34
yep..
Avatar billede roenving Novice
21. juni 2004 - 03:16 #35
Men en match giver som resultat et array, så sådan en tingest opfører sig vel som et array, du bagefter kan replace på de enkelte elementer ?-)
Avatar billede tbm_iceman Nybegynder
21. juni 2004 - 03:18 #36
nej ikke helt... for det den gør at den returnerer hele strengen altså alt HTML med også.... dvs det er en grov sortering... det jeg skal bruge er nu en måde at extracte () ud af den.... ligesom man i en Replace får dem ud med $1 osv... det er det jeg leder efter... :/
Avatar billede roenving Novice
21. juni 2004 - 03:22 #37
Jeg ville prøve:

    dim strText
    i=0
    For Each Match in Matches                ' Iterate Matches collection.
        strText(i) = RegExp.Replace(Match, "$1$2$3$4$5$6" & Chr(13))
        i = i + 1
    Next
Avatar billede tbm_iceman Nybegynder
21. juni 2004 - 03:23 #38
hehe... faktisk det jeg sidder og laver lige nu... :P
Avatar billede tbm_iceman Nybegynder
21. juni 2004 - 03:24 #39
her er den der virker...

    Set Matches = RegExp.Execute(strText)    ' Execute search.

    For Each Match in Matches                ' Iterate Matches collection.
        strNew = strNew & RegExp.Replace(Match.Value, "$1" & Chr(9) & "$2" & Chr(9) & "$3" & Chr(9) & "$4" & Chr(9) & "$5" & Chr(9) & "$6") & Chr(13)
    Next

bare så du ved det til en anden gang der kommer en og spørger..
Avatar billede roenving Novice
21. juni 2004 - 03:27 #40
Ski**godt, resultatet ligner i allerhøjeste grad en .csv-fil !-)
Avatar billede tbm_iceman Nybegynder
21. juni 2004 - 03:28 #41
yep.. :) ... og nu er det klar til at blive smidt ind i et 2 dimensionelt array og videre derfra til en sql DB.. og så er aftenens strabadser forbi...
Avatar billede Slettet bruger
26. juni 2004 - 13:09 #42
roenving: Normalt er * grådig. Dvs. den vælger det længste mulige match. Ved at sætte et ? bagefter gøres den ikke-grådig. Hvis alle * i en RegEx skal være ikke-grådige, kan man normalt sætte en option til det. I Perl eller PHPs preg-funktioner gøres det med et U som i /pattern/U
Avatar billede tbm_iceman Nybegynder
26. juni 2004 - 20:55 #43
sandbox: tak for din kommentar... :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester