ycc skrev:
Den inledande frågeställningen om hur man undviker att sed jobbar på kommentarer och citat är ju nog snabbt löst med regexp.
Jag är ledsen men regexp klarar helt enkelt inte av det.
ycc skrev:
Kod: Markera allt
$ cat tst
Behåll blanka här %%%% Byt blanka mot understrykning här
$ cat tst | sed -r ':a;s/^(.*% [^ ]*) /\1_/;ta'
Behåll blanka här %%%% Byt_blanka__mot_understrykning_här
Om man ska jämföra med strängar. Byt ut % mot " i exemplet ovan:
Kod: Markera allt
inte här " understyk här " inte här " undestryk här " inte här
Man måste helt enkelt räkna varje " ända från
början av filen. Processen måste ta ställning till
varje tecken. Hoppar man över
ett enda tecken kan det bli fel. Lägg därtill att om " föregås av \ ska den inte räknas.
Kod: Markera allt
inte här " understyk här \" undestryk här " inte här
Om vi bara har vanliga strängar " " att ta hänsyn till. Då går det att göra ett
igenkännande regexp:
/\A([^"]+|"([^"\\]|\\.)*")*x/
Det hittar ett x som garanterat inte finns i en sträng. Det går t.o.m att göra ett uttryck för sed som byter ut x mot *. Men vad göra om det finns
flera x?
Så redan här, när vi bara har " att ta hänsyn till,
om det ska göras nåt med
varje förekomst av x som
inte är i en sträng så blir sed och regexp helt
otillräckligt.
Men det är värre än så
Vi har inte bara ". Vi har ', /*, */, //, och nyrad.
" ska inte räknas inom ' '.
' ska inte räknas inom " ".
Varken " eller ' ska räknas inom /* */ eller // nyrad.
// ska inte räknas inom /* */.
/* ska inte räknas inom // nyrad.
Varken /* och // ska inte räknas inom " " och ' '.
Varken " och ' ska räknas direkt efter \ .
Kanske att det finns en guru i världen som kan göre ett
igenkännande regexp som klarar allt detta, men det blir väldigt komplicerat och obegripligt. Och den kommer inte att klara att byta ut flera förekomster av x till *, inte i sed.
Perl-snutten i tidigare inlägg tittar på
vartenda tecken i hela filen. Den klarar att byta ut flera förekomster av x till *. Den byter
inte i strängar (' ' och " ") och kommentarer (/* */ och // nyrad). Den låter sig inte luras av /* och // i strängar eller av ' och " i kommentarer. Den använder
regexp, men i dess huvudstruktur är den en
tokenizer. (Flera små regexp används för att känna igen olika tokens.)
Och som sagt. När vi inför ² i ekvationen räcker inte en tokenizer, då måste vi ha en
parser.
Utvikning
Prisjämförelsesajter som Prisjakt och Pricerunner, hur vet de vilka priser olika varor har på olika säljsajter? Troligen (förhoppningsvis) har säljsajterna APIn. Om inte så får prisjämförelsesajterna ha program som parsar html-koden för att hitta varans namn och pris och liknande. Säg att htmlkoden för en bok ser ut så här
Kod: Markera allt
<div class="title"> Liftarens guide till Galaxen </div>
<div class="price"> 49 kronor </div>
<div class="sample"> "Adjö och tack för fisken" </div>
Tänk om de använder regexp för att hitta priset
/class="price".*([0-9]+)/
Tänk om priset har ändrats och det gamla priset ligger kvar i en html-kommentar:
Kod: Markera allt
<div class="title"> Liftarens guide till Galaxen </div>
<!-- Gammalt pris <div class="price"> 59 kronor </div>-->
<div class="price"> 49 kronor </div>
<div class="sample"> "Adjö och tack för fisken" </div>
Vilket pris kommer då att visas på sajten? Vad händer om nåt som ser ut som html-fragment förekommer i texten:
Kod: Markera allt
<div class="title"> En konstig roman av David </div>
<div class="price"> 89 kronor </div>
<div class="sample"> Hon: Jag älskar dej! Han: class="price". Hon: Va? </div>