Dagens bugg

Följande kod, djupt nere i innanmätet på lagen.nu 1.0-koden, har en
bugg, som stått orättad i över tre år (det den ska göra är att stoppa in ett ‘|’-tecken innan ändelser i
stil med ‘lagen’, ‘balken’, osv — dvs ‘upphovsrättslagen’ ska bli
‘upphovsrätts|lagen’ — detta av
EBNF-tekniska skäl
.

fixedindata = re.sub(r'\B(lagens?|balkens?|förordningens?)\b',
                     r'|\1', self.indata)

Hittar ni felet? Ledtråd — det uppträder bara för en av de tio
balkarna, samt för ett mycket litet fåtal lagar och förordningar.

7 reaktioner till “Dagens bugg”

  1. Styggt med svenska tecken. Men det här funkar ju iaf.

    >>> print re.sub(r'(?! )(lagens?|balkens?|förordningens?)\b’, r’|\1′, u’miljöbalken’)
    miljö|balken

    🙂

  2. Rätt identifierat, men fel fixat (ledning: hur funkar det för ”arbetsmiljölagen”?)

    Min lösning blev att tvinga python att förstå att \B inte skulle betrakta svenska bokstäver som word boundaries genom att tala om att jag vill ha en localesensitiv lösning:

    import locale
    locale.setlocale(locale.LC_ALL,”)
    rex = re.compile(r’\B(lagens?|balkens?|förordningens?)\b’, re.LOCALE)
    fixedindata = rex.sub(r’|\1′, self.indata)

  3. Öh… det funkar väl fint för “arbetsmiljölagen”

    >>> print re.sub(r'(?! )(lagens?|balkens?|förordningens?)\b’, r’|\1′, u’arbetsmiljölagen’)
    arbetsmiljö|lagen

    Eller missar jag nåt? 🙂

  4. Nej, det är jag som inte kan läsa — din lösning funkar utmärkt även för det fallet. Däremot verkar den även matcha den ”lagen” m.fl strängar även när de står fristående, vilket alltså inte är tanken:

    >>> re.sub(r'(?! )(lagens?|balkens?|förordningens?)\b’, r’|\1′, u’enligt lagen’)
    u’enligt |lagen’

    Spontant förstår jag inte varför inte (?!…)-konstruktionen inte gör det jag trodde den skulle göra, men man kan notera att det inte bara är mellanslag som kan utgöra word boundary — andra exempelsträngar som inte ska matcha är u’enligt\nlagen’, u’enligt\xa0lagen’ och u’enligt\tlagen’.

    Istället för att själv tänka igenom alla möjliga tecken som utgör word boundaries vill jag utnyttja att nån annan tänkt igenom det i implementationen av \B i pythons regexpmotor. Men det gäller att få den att förstå att ”ö” inte är en word boundary.

  5. Uj, menade (?>> print re.sub(r'(?<!\s)(lagens?|balkens?|förordningens?)\b’, r’|\1′, u’foo\nmiljöbalken.’)
    foo
    miljö|balken.

    🙂
    Men jag fattar och håller nog nästan med om att det är finare att göra det med word boundaries.

  6. Uh… wordpress filtrerade bort rätt bra i förra inlägget. Testar igen.

    >>> print re.sub(r'(?<!\s)(lagens?|balkens?|förordningens?)\b’, r’|\1′, u’foo\nmiljöbalken.’)
    foo
    miljö|balken.

  7. ”Istället för att själv tänka igenom alla möjliga tecken som utgör word boundaries vill jag utnyttja att nån annan tänkt igenom det i implementationen av \B i pythons regexpmotor.”

    Varandes den personen 😉 så vill jag bara påpeka att eftersom du redan använder Unicode för texten så är lösningen att tala om för regexp-motorn att den ska använda Unicode-regler, vilket du gör med ett ”(?u)” först i mönstret:

    >>> re.sub(r”(?u)\B(lagens?|balkens?|förordningens?)\b”,
    r”|\1″, u’arbetsmiljöbalken.’)
    u’arbetsmilj\xf6|balken.’

    (alternativt använd re.UNICODE istället för re.LOCALE)

Kommentarer kan inte lämnas på detta inlägg.