Perl-kompatibla reguljära uttryck

Perl-kompatibla reguljära uttryck
Originalförfattare Philip Hazel
Stabila utgåvor
PCRE1 8.45 / 15 juni 2021 ; 20 månader sedan ( 2021-06-15 )
PCRE2 10.40 / 15 april 2022 ; 10 månader sedan ( 2022-04-15 )
Förvar
Skrivet i C
Operativ system Cross-plattform
Typ Mönstermatchande bibliotek
Licens BSD
Hemsida pcre .org Edit this at Wikidata

Perl Compatible Regular Expressions ( PCRE ) är ett bibliotek skrivet i C , som implementerar en motor för reguljära uttryck , inspirerad av funktionerna i programmeringsspråket Perl . Philip Hazel började skriva PCRE sommaren 1997. PCREs syntax är mycket kraftfullare och mer flexibel än någon av POSIX reguljära uttryckssmakerna (BRE, ERE) och än många andra reguljära uttrycksbibliotek.

Medan PCRE ursprungligen syftade till funktionslikvärdighet med Perl, är de två implementeringarna inte helt likvärdiga. Under fasen PCRE 7.x och Perl 5.9.x samordnade de två projekten utvecklingen, med funktioner som portades mellan dem i båda riktningarna.

Under 2015 släpptes en gaffel av PCRE med ett reviderat programmeringsgränssnitt (API). Den ursprungliga programvaran, nu kallad PCRE1 (1.xx–8.xx-serien), har fått buggar lagade, men ingen vidareutveckling. Från och med 2020 anses den vara föråldrad, och den nuvarande 8.45-versionen kommer sannolikt att vara den sista. Den nya PCRE2-koden (10.xx-serien) har fått ett antal tillägg och kodningsförbättringar och det är där utvecklingen sker.

Ett antal framstående program med öppen källkod , som Apache- och Nginx HTTP-servrarna, och PHP- och R -skriptspråken, innehåller PCRE-biblioteket; proprietär programvara kan göra likadant, eftersom biblioteket är BSD-licensierat. Från och med Perl 5.10 är PCRE också tillgänglig som en ersättning för Perls standardmotor för reguljärt uttryck genom re::engine::PCRE- modulen.

Biblioteket kan byggas på Unix, Windows och flera andra miljöer. PCRE2 distribueras med ett POSIX C-omslag, flera testprogram och verktygsprogrammet pcre2grep som är byggt i tandem med biblioteket.

Funktioner

Just-in-time kompilatorstöd

Denna valfria funktion är tillgänglig om den är aktiverad när PCRE2-biblioteket byggs. Stora prestandafördelar är möjliga när (till exempel) det anropande programmet använder funktionen med kompatibla mönster som exekveras upprepade gånger. Just-in-time kompilatorstödet skrevs av Zoltan Herczeg och tas inte upp i POSIX-omslaget.

Flexibel minneshantering

Användningen av systemstacken för backtracking kan vara problematisk i PCRE1, varför denna funktion i implementeringen ändrades i PCRE2. Högen används nu för detta ändamål, och den totala mängden kan begränsas. Problemet med stackoverflow , som kom upp regelbundet med PCRE1, är inte längre ett problem med PCRE2 från release 10.30 (2017).

Konsekventa flyktregler

Precis som Perl har PCRE2 konsekventa escape-regler: alla icke-alfanumeriska tecken kan escapes för att betyda dess bokstavliga värde genom att prefixet \ (omvänt snedstreck ) före tecknet. Alla alfanumeriska tecken som föregås av ett snedstreck ger det vanligtvis en speciell betydelse. I det fall där sekvensen inte har definierats som speciell, uppstår ett fel. Detta skiljer sig från Perl, som bara ger ett fel om den är i varningsläge (PCRE2 har inget varningsläge). I vanliga reguljära POSIX-uttryck undkom omvänt snedstreck ibland icke-alfanumeriska tecken (t.ex. \. ), och ibland introducerade de en speciell funktion (t.ex. \(\) ).

Utökade karaktärsklasser

Enbokstavsklasser stöds utöver de längre POSIX-namnen . Till exempel matchar \d vilken siffra som helst precis som [[:siffra:]] skulle göra i POSIX reguljära uttryck.

Minimal matchning (aka "ogrådig")

A ? kan placeras efter valfri upprepningskvantifierare för att indikera att den kortaste matchningen ska användas. Standard är att försöka den längsta matchningen först och gå tillbaka genom kortare matchningar: t.ex. a.*?b skulle matcha första "ab" i "ababab", där a.*b skulle matcha hela strängen.

Om U -flaggan är inställd, är kvantifierare ogråliga (lata) som standard, medan ? gör dem giriga.

Unicode-teckenegenskaper

Unicode definierar flera egenskaper för varje tecken. Mönster i PCRE2 kan matcha dessa egenskaper: t.ex. \ p { Ps } .*? \ p { Pe } skulle matcha en sträng som börjar med valfri "öppnande interpunktion" och slutar med valfri "nära interpunktion" såsom [abc] . Matchning av vissa "normala" metatecken kan drivas av Unicode-egenskaper när kompileringsalternativet PCRE2_UCP är inställt. Alternativet kan ställas in för ett mönster genom att inkludera (*UCP) i början av mönstret. Alternativet ändrar beteendet för följande metatecken: \B , \b , \D , \d , \S , \s , \W , \w , och några av POSIX-teckenklasserna. Till exempel utökas uppsättningen tecken som matchas av \w (ordtecken) till att inkludera bokstäver och bokstäver med accent enligt Unicode-egenskaper. Sådan matchning är långsammare än det normala ( endast ASCII ) icke-UCP-alternativet. Observera att UCP-alternativet kräver att biblioteket har byggts för att inkludera Unicode-stöd (detta är standard för PCRE2). Mycket tidiga versioner av PCRE1 stödde endast ASCII-kod. Senare lades UTF-8-stöd till. Stöd för UTF-16 lades till i version 8.30 och stöd för UTF-32 i version 8.32. PCRE2 har alltid stött alla tre UTF-kodningarna.

Flerlinjematchning

^ och $ kan bara matcha i början och slutet av en sträng, eller i början och slutet av varje "rad" i strängen, beroende på vilka alternativ som är inställda.

Alternativ för ny linje/radbrytning

När PCRE kompileras väljs en ny linjestandard. Vilken nyrad/radbrytning som är i kraft påverkar var PCRE upptäcker ^ radstarter och $ slut (i flerradsläge), samt vad som matchar punkt (oavsett multilinjeläge, om inte dotall-alternativet ( ?s) är inställt). Det påverkar också PCRE-matchningsproceduren (sedan version 7.0): när ett oförankrat mönster inte matchar i början av en nyradssekvens, går PCRE förbi hela nyradssekvensen innan matchningen görs igen. Om alternativet för nyradsalternativ i praktiken inkluderar CRLF som en av de giltiga radbrytningarna, hoppar det inte över \ n i en CRLF om mönstret innehåller specifika \r eller \n referenser (sedan version 7.3). Sedan version 8.10 matchar metateckenet \N alltid alla andra tecken än radbrytningstecken. Den har samma beteende som . när dotall-alternativet aka (?s) inte är aktivt.

Newline-alternativet kan ändras med externa alternativ när PCRE kompileras och när det körs. Vissa applikationer som använder PCRE ger användarna möjlighet att tillämpa denna inställning via ett externt alternativ. Så newline-alternativet kan också anges i början av mönstret med något av följande:

  • (*LF) Newline är ett radmatningstecken. Motsvarande radbrytningar kan matchas med \n .
  • (*CR) Newline är en vagnretur. Motsvarande radbrytningar kan matchas med \r .
  • (*CRLF) Newline/linebreak är en vagnretur följt av en radmatning. Motsvarande radbrytningar kan matchas med \r\n .
  • (*ANYCRLF) Något av ovanstående som påträffas i data kommer att utlösa nyradsbehandling. Motsvarande radbrytningar kan matchas med (?: \ r \ n ?| \ n ) eller med \R . Se nedan för konfiguration och alternativ för vad som matchar backslash-R.
  • (*ANY) Något av ovanstående plus speciella Unicode-radbrytningar.

När den inte är i UTF-8-läge kan motsvarande radbrytningar matchas med (?: \ r \ n ?| \ n | \ x0B | \ f | \ x85 ) eller \R .

I UTF-8-läge känns ytterligare två tecken igen som radbrytningar med ( *ANY) :

  • LS (linjeavgränsare, U+2028),
  • PS (styckeavskiljare, U+2029).

På Windows, i icke-Unicode-data, har några av ALLA radbrytartecken andra betydelser.

Till exempel kan \x85 matcha en horisontell ellips, och om den påträffas medan NÅGON nyrad är aktiv, skulle den utlösa nyradsbehandling.

Se nedan för konfiguration och alternativ för vad som matchar backslash-R.

Alternativ för backslash-R

När PCRE kompileras väljs en standard för det som matchar \R . Standard kan vara antingen att matcha radbrytningarna som motsvarar ANYCRLF eller de som motsvarar ANY. Standardinställningen kan åsidosättas vid behov genom att inkludera (*BSR_UNICODE) eller (*BSR_ANYCRLF) i början av mönstret. När du tillhandahåller ett (*BSR..) -alternativ kan du också tillhandahålla ett (* newline ) , t.ex. (*BSR_UNICODE)(*ANY) rest-of-pattern . Alternativen för backslash-R kan också ändras med externa alternativ av applikationen som anropar PCRE2, när ett mönster kompileras.

Början av mönsteralternativ

Linjebrytningsalternativ som (*LF) dokumenterade ovan; backslash-R-alternativ såsom (*BSR_ANYCRLF) dokumenterade ovan; Alternativet Unicode Character Properties (*UCP) dokumenterat ovan; (*UTF8) -alternativet dokumenterat enligt följande: om ditt PCRE2-bibliotek har kompilerats med UTF- stöd, kan du ange alternativet (*UTF) i början av ett mönster istället för att ställa in ett externt alternativ för att anropa UTF-8, UTF-16 , eller UTF-32-läge.

Bakåtreferenser

Ett mönster kan referera till resultaten från en tidigare match. Till exempel (a|b)c\1 matcha antingen "aca" eller "bcb" och skulle inte matcha till exempel "acb".

Namngivna undermönster

Ett undermönster (omgivet av parenteser, som (...) ) kan namnges genom att inkludera ett inledande ?P<namn> efter den inledande parentesen. Namngivna undermönster är en funktion som PCRE antog från Python reguljära uttryck.

Denna funktion antogs senare av Perl, så nu kan namngivna grupper också definieras med (?<namn>...) eller (?'namn'...) samt (?P<namn>...) . Namngivna grupper kan återföras med till exempel: (?P=namn) (Python-syntax) eller \k'name' (Perl-syntax).

Subrutiner

Medan en tillbakareferens tillhandahåller en mekanism för att hänvisa till den del av motivet som tidigare har matchat ett delmönster, tillhandahåller en subrutin en mekanism för att återanvända ett underliggande tidigare definierat delmönster. Undermönstrets alternativ, såsom ärendeoberoende, är fasta när undermönstret definieras. (ac)(?1) skulle matcha "aacabc" eller "abcadc", medan användning av en backreferens (ac)\1 inte skulle matcha "aacaac" eller "abcabc". PCRE stöder också en icke-Perl Oniguruma- konstruktion för subrutiner. De anges med \g<subpat-number> eller \g<subpat-name> .

Atomgruppering

Atomgruppering är ett sätt att förhindra att ett mönster går tillbaka . Till exempel kommer a++bc att matcha så många "a" som möjligt och säkerhetskopiera aldrig för att prova ett mindre.

Titta framåt och se-bakom påståenden

Påstående Kolla bakom Se framåt
Positiv (? <= mönster ) (? = mönster )
Negativ (? <! mönster ) (? ! mönster )

Titta-bak- och se-framåt-påståenden i Perl reguljära uttryck

Mönster kan hävda att föregående text eller efterföljande text innehåller ett mönster utan att konsumera matchad text (nollbreddspåstående). Till exempel matchar / \w+(?=\t) / ett ord följt av en tabb , utan att ta med själva tabben.

Look-behind-påståenden kan inte vara av osäker längd även om (till skillnad från Perl) varje gren kan ha olika fast längd.

\K kan användas i ett mönster för att återställa starten av den aktuella hela matchen. Detta ger ett flexibelt alternativt tillvägagångssätt för att se bakom påståenden eftersom den kasserade delen av matchningen (delen som föregår \K ) inte behöver fixeras i längd.

Escape-sekvenser för nollbreddspåståenden

Till exempel \b för att matcha "ordgränser" med noll bredd, liknande (? < = \ W )(?= \ w )|(? < = \ w )(?= \ W )|^|$ .

Kommentarer

En kommentar börjar med (?# och slutar vid nästa avslutande parentes.

Rekursiva mönster

Ett mönster kan referera tillbaka till sig självt rekursivt eller till vilket delmönster som helst. Till exempel kommer mönstret \ (( a *|(? R ))* \ ) att matcha vilken kombination av balanserade parenteser och "a" som helst.

Generiska bildtexter

PCRE-uttryck kan bädda in (?Cn ) , där n är ett tal. Detta kommer att anropa en extern användardefinierad funktion via PCRE API och kan användas för att bädda in godtycklig kod i ett mönster.

Skillnader från Perl

Skillnader mellan PCRE2 och Perl (från Perl 5.9.4) inkluderar men är inte begränsade till:

Fram till release 10.30 var rekursiva matchningar atomära i PCRE och icke-atomära i Perl

Detta innebar att "<<!>!>!>><>>!>!>!>" =~ /^(<(?:[^<>]+|(?3)|(?1))* >)()(!>!>!>)$/ skulle matcha i Perl men inte i PCRE2 förrän release 10.30.

Värdet på en fångstbuffert som härrör från ? kvantifierare (matcha 1 eller 0 gånger) när den är kapslad i en annan kvantifierad fångstbuffert är annorlunda

I Perl "aba" =~ /^(a(b)?)+$/ ; kommer att resultera i att $1 innehåller "a" och $2 som innehåller undef , men i PCRE kommer att resultera i att $2 innehåller "b".

PCRE tillåter att namngivna infångningsbuffertar ges numeriska namn; Perl kräver att namnet följer regeln om blotta ord

Detta betyder att \g{} är entydig i Perl, men potentiellt tvetydig i PCRE.

Detta är inte längre någon skillnad sedan PCRE 8.34 (släppt 2013-12-15), som inte längre tillåter gruppnamn att börja med en siffra.

PCRE tillåter alternativ inom lookbehind att vara olika långa

Inom lookbehind-påståenden kräver både PCRE och Perl mönster med fast längd.

Det vill säga, både PCRE och Perl tillåter inte mönster med variabel längd med hjälp av kvantifierare inom lookbehind-påståenden.

Perl kräver dock att alla alternativa grenar av en lookbehind-påstående är lika långa som varandra, medan PCRE tillåter att de alternativa grenarna har olika längder från varandra så länge som varje gren fortfarande har en fast längd.

PCRE stöder inte vissa "experimentella" Perl-konstruktioner

Såsom (??{...}) (en callback vars avkastning utvärderas som en del av mönstret) eller (?{}) -konstruktionen, även om den senare kan emuleras med (?Cn) .

Rekursionskontrollverb som lagts till i Perl 5.9.x-serien stöds inte heller.

Stöd för experimentella backtracking-kontrollverb (tillagda i Perl 5.10) är tillgängligt i PCRE sedan version 7.3.

De är (*FAIL) , (*F) , (*PRUNE) , (*SKIP) , (*THEN) , (*COMMIT) och (*ACCEPTERA) .

Perls motsvarande användning av argument med backtracking kontrollverb stöds inte generellt.

Observera dock att sedan version 8.10 stöder PCRE följande verb med ett specificerat argument: (*MARK:markName) , (*SKIP:markName) , (*PRUNE:markName) och (*THEN:markName) .

Sedan version 10.32 har PCRE2 stöd för (*ACCEPT:markName) , (*FAIL:markName) och (*COMMIT:markName) .

PCRE och Perl är något olika i sin tolerans för felaktiga konstruktioner

Perl tillåter kvantifierare på (?!...) konstruktionen, som är meningslös men harmlös (om än ineffektiv); PCRE ger ett fel i versioner före 8.13.

PCRE har en hård gräns för rekursionsdjup, det har inte Perl

Med standardbyggalternativ "bbbbXcXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" =~ /.X(.+)+X/ kommer inte att matcha på grund av gränsen, men Perl kommer att matcha detta korrekt.

Perl använder högen för rekursion och har ingen hård gräns för rekursionsdjup, medan PCRE2 har en standardgräns för kompileringstid som kan justeras upp eller ner av den anropande applikationen.

Verifiering

Med undantag för ovanstående punkter kan PCRE klara testerna i Perl " t/op/re_tests "-filen, ett av de viktigaste regressionstesterna på syntaxnivå för Perls reguljära uttrycksmotor.

Anteckningar och referenser

Anteckningar

  1. ^ Kärnan i PCRE2-biblioteket tillhandahåller både matchnings- och matchnings- och ersättningsfunktioner.
  2. ^

    Säker på att \ x85 - delen inte är \ xC2 \ x85 ? (dvs (?: \ r \ n ?| \ n | \ x0B | \ f | \ xC2 \ x85 ) , som U+0085 != 0x85) Varning : Om mönstret \ xC2 \ x85 inte fungerade: experimentera med RegEx-implementeringens Unicode-inställningar, eller försök ersätta med följande:
    • \ x { 0085 }
    • \ u0085

Referenser

  1. ^ Slutlig version av PCRE1: https://lists.exim.org/lurker/message/20210615.162400.c16ff8a3.en.html
  2. ^ Releaser: https://github.com/PCRE2Project/pcre2/releases
  3. ^ Exim och PCRE: How free software hijacked my life (1999-12), av Philip Hazel , sid. 7: https://www.ukuug.org/events/winter99/proc/PH.ps

    Hur är det med PCRE?

    • Skrivet sommaren 1997, placerat på ftp-sajt.
    • Folk hittade det och startade en e-postlista.
    • Det har skett en rännil av förbättringar.
  4. ^
  5. ^ PCRE2 - Perl-kompatibla reguljära uttryck (reviderat API) (2020), av University of Cambridge : https://pcre.org/pcre2.txt
  6. ^ Skillnader mellan PCRE2 och Perl (2019-07-13), av Philip Hazel : https://www.pcre.org/current/doc/html/pcre2compat.html
  7. ^ Citera PCRE changelog ( https://www.pcre.org/original/changelog.txt ): "Perl tillåter inte längre gruppnamn att börja med siffror, så jag har gjort denna ändring även i PCRE."
  8. ^ ChangeLog för PCRE2: https://www.pcre.org/changelog.txt

Se även

externa länkar