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.

Tags:

7 Responses to “Dagens bugg”

  1. buffi Says:

    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. staffan Says:

    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. buffi Says:

    Ö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. staffan Says:

    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. buffi Says:

    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. buffi Says:

    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. Fredrik Says:

    “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)

Leave a Reply