Avatar billede breum Nybegynder
15. juni 2006 - 14:49 Der er 8 kommentarer og
1 løsning

Udsnit af variabel

Følgende virker ikke efter hensigten, hvad skal jeg gøre for at det virker:
$variabel='<!-- TotAllPax ..... 3922.0  --><table';

if ($variabel =~ /<!-- TotAllPax ..... ([^t]*)  --><table/i)
        {
        $tal = $1;
        }
print "$tal burde være = 3922.0\n";

Selv når jeg backslasher får jeg det ikke med
Avatar billede breum Nybegynder
15. juni 2006 - 15:05 #1
Tilsyneladende virker koden i ovenstående efter hensigten, min fejl må være andetsteds, jeg lukker formentlig spg om lidt
Avatar billede nielle Nybegynder
15. juni 2006 - 16:08 #2
Jeg ved ikke hvorfor du bruger [^t] for at matche et tal - det betyder nemlig "noget som ikke er et 't'.

Et mere korrekt møster ville være:

if ($variabel =~ /<!-- TotAllPax ..... ([1-9]\d*(\.\d+)?)  --><table/i)
Avatar billede nielle Nybegynder
15. juni 2006 - 18:04 #3
... eller endnu bedre:

if ($variabel =~ /<!-- TotAllPax ..... ([1-9]\d*(?:\.\d+)?)  --><table/i)
Avatar billede breum Nybegynder
16. juni 2006 - 09:27 #4
t var for t et i table, da jeg ikke kunne få det til at virke med whitespace karaktererne
Avatar billede breum Nybegynder
16. juni 2006 - 09:27 #5
eller tabulatortegn
Avatar billede breum Nybegynder
16. juni 2006 - 09:31 #6
kan du oversætte din match det vil jeg sætte stor pris på, jeg forstår den ikke 100%

og drop venligst et svar så jeg kan give dig points
Avatar billede breum Nybegynder
16. juni 2006 - 09:32 #7
det så iøvrigt ud til at ^t fangede tabulatortegnet er det forkert opfattet
Avatar billede nielle Nybegynder
16. juni 2006 - 12:00 #8
Tabulatortegn matches som \t.

Et tabulatortegn er desuden et whitespace tegn, og det kan derfor også matches med \s.

[^t] fanger som sagt ”et tegn som ikke er et ’t’”. Imidlertid matcher det *ikke* normalt whitespace-tegn af den grund, og derfor matcher det heller ikke et tabulatortegn. Man kan dog tvinge den til at gøre dette ved at smække en s-modifikator på din matchning:

if ($variabel =~ /<!-- TotAllPax ..... ([^t]*)  --><table/is)

s’er stå for at den skal behandle teksten som ”singleline”.

Mit mønster, ([1-9]\d*(?:\.\d+)?), i:

if ($variabel =~ /<!-- TotAllPax ..... ([1-9]\d*(?:\.\d+)?)  --><table/i)

- skal læses sådan:

[...] – et []-par matcher et af de tegn som befinder sig inden i dem, og derfor gælder:

[1-9] - matcher ”et af tegnene 1, 2, 3, 4, 5, 6, 7, 8 eller 9”. Grunden til at mønsteret startes på denne måde er at sikre at det tal som matches ikke kan begynde med 0.

\d – matcher ”et ciffer” altså ”et af tegnene 0, 1, 2, 3, 4, 5, 6, 7, 8 eller 9”.

* - er en modifier som betyder ”0 eller flere gange”, og derfor gælder:

\d* - matcher ”0 eller flere gange af tegnene 0, 1, 2, 3, 4, 5, 6, 7, 8 eller 9”

Slås dette sammen til den første del af mit mønster:

[1-9]\d* - matcher ”et af tegnene 1, 2, 3, 4, 5, 6, 7, 8 eller 9 efterfulgt af 0 eller flere gange af tegnene 0, 1, 2, 3, 4, 5, 6, 7, 8 eller 9”. Man kan også bare sige at det matcher ”et heltal”.

Nu var jeg ikke sikker på om dit tal altid havde en decimaldel med, og derfor var mønsteret ikke færdigt med det. Den anden halvdel af mønsteret, (?:\.\d+)?), matcher netop decimaldelen hvis den er der:

. – Et punktum matcher ”et vilkårligt tegn”. Imidlertid havde vi ikke brug for et vilkårligt tegn, men kun et punktum og ikke noget andet (dit tal bruger jo decimalpunktum). Derfor er vi nødt til at ”escape” punktum sådan at det nu matcher ”et punktum” og ikke det altomfavnende ”et vilkårligt tegn”. En escapning laves ved at smælle et \-tegn foran:

\. – matcher ”et punktum”

Hvis der er et decimalpunktum i tallet, så er der nødvendigvis også nogle tal efter dette:

\.\d+ - \d matcher som sagt ”et af tegnene 0, 1, 2, 3, 4, 5, 6, 7, 8 eller 9”, og så er der kun et +-tegn som skal forklares. Hvor *-tegnet betyder ”0 eller flere gange”, så betyder et +-tegn ”1 eller flere gange”. Derfor matcher ” \.\d+” altså ”et punktum efter fulgt af 1 eller flere gange af tegnene 0, 1, 2, 3, 4, 5, 6, 7, 8 eller 9”.

Siden at jeg ikke var sikker på at decimaldelen altid skulle med, så gjorde jeg den frivillige ved at smække dem indenfor i en:

(...)? – ()-parret grupperer alt det der er imellem dem, og ?-tegnet betyder at denne gruppe kan udelades hvis det ikke er muligt at matche dem. I dette tilfælde gælder:

(\.\d+)? – matcher ”et punktum efter fulgt af 1 eller flere gange af tegnene 0, 1, 2, 3, 4, 5, 6, 7, 8 eller 9 ELLER ingenting”. Jeg kommer tilbage til det ekstra ”?:” lige om lidt.

Nu har vi altså:

[1-9]\d*(\.\d+)? - matcher ”et heltal, med eller uden en decimaldel”.

Det der er matchet vil du gerne have ud i din $1, og det gøre sved at smække et grupperende ()_par rundt om det:

([1-9]\d*(\.\d+)?)

Men hov, nu er der jo faktisk 2 grupperende parentespar! Hvad sker der så? Svaret er at, der sker faktisk ikke noget specielt, du får faktisk dit tal ud som $1.

Men egentligt bruger vi ikke den indre parentes til noget andet end at gruppere decimaldelen. Derfor behøver vi heller ikke at afsætte ressourcer til at programmet skal huske hvad der er inden i det indre parentespar. Det er så her at ”?:” kommer ind:

(?:\.\d+)? – matcher fortsat ”et punktum efter fulgt af 1 eller flere gange af tegnene 0, 1, 2, 3, 4, 5, 6, 7, 8 eller 9 ELLER ingenting”, men med den krølle at vi ikke senere kan udtrække det mellem parenteserne som f.eks. $2. Det er altså bare en lille effektivisering som man kan vælge at have med eller udelade hvis man vil.

Håber at det forklarede sagen tilfredsstillende? Ellers må du jo bare spørge.:^)
Avatar billede breum Nybegynder
16. juni 2006 - 15:21 #9
Meget tilfredsstillinde!

Tak for hjælpen!
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