Permalänk
Medlem

php regex

Tjabba,

Jag håller på med en liten funktion.
Jag får inte riktigt till denna regex som jag vill, hur gör jag om jag vill att den ska fungera såhär:

"/@(\w{4,15}?)([:dot]|!|\s)/is" men ej ta med . eller !, som det är nu ifall strängen är låt säga: @teststräng. så blir den teststräng, jag vill alltså att sista tecknet den ska ta med är det före . eller ! är det möjligt öht?

ursäkta röran känns som att jag är sämst på att beskriva vad jag är ute efter

Visa signatur

Citera om du vill ha svar :)

Permalänk
Geeks
Jobbar med data

Matchar hur många tecken som helst innan . ! (mellanslag)
https://regex101.com/r/hZJwOS/1
Matchar 4-15 tecken som innan . ! (mellanslag)
https://regex101.com/r/paN8sq/1

Jag har lagt på /g för att jag skulle kunna visa exempel på flera rader.

Permalänk
Medlem
Skrivet av jreklund:

Matchar hur många tecken som helst innan . ! (mellanslag)
https://regex101.com/r/hZJwOS/1
Matchar 4-15 tecken som innan . ! (mellanslag)
https://regex101.com/r/paN8sq/1

Jag har lagt på /g för att jag skulle kunna visa exempel på flera rader.

Denna gör samma sak, eftersom skiljetecken inte ingår i word characters. Ganska ny till regex och har mest arbetat i .Net, så det kanske är någonting som man borde göra annorlunda i PHP

Visa signatur

| EVGA Z170 FTW | i7 6700k | ASUS RTX 3070 | 16GB DDR4 3200MHz | Cooler Master V850 | Samsung 840 Evo 250GB + 2x WD Black 500GB + Seagate 2TB SSHD + Samsung 970 Evo M.2 1TB|

Permalänk
Medlem
Skrivet av jreklund:

Matchar hur många tecken som helst innan . ! (mellanslag)
https://regex101.com/r/hZJwOS/1
Matchar 4-15 tecken som innan . ! (mellanslag)
https://regex101.com/r/paN8sq/1

Jag har lagt på /g för att jag skulle kunna visa exempel på flera rader.

Tack det fungerar nästan som tänkt hur gör jag riktigt om det bara ska ta med a-öA-Ö0-9_-?

såhär ser funtionen ut just nu

function test($body) { $find = array( "/\[quote\](.+?)\[\/quote\]/is", "/@[^\.|!|\s]{4,15}/" ); $replace = array( "<div class=\"quote\">$1</div>", "<a href=\"user.php?profile=$1\">$1</a> " ); $body = htmlspecialchars($body); $body = preg_replace($find, $replace, $body); return $body;

Visa signatur

Citera om du vill ha svar :)

Permalänk
Geeks
Jobbar med data

@BrutalSwede: Den är 6 steg långsammare, annars är det ingen skillnad.

EDIT: Missade att du hade en capture group. Därför 6 steg extra. Annars ingen skillnad.

Permalänk
Medlem
Skrivet av BrutalSwede:

Denna gör samma sak, eftersom skiljetecken inte ingår i word characters. Ganska ny till regex och har mest arbetat i .Net, så det kanske är någonting som man borde göra annorlunda i PHP

Det där fungerade ypperligt, går det att få så den tar med åäö också? som jag förstått är \w a-zA-Z0-9_?

detta fungerade: "/@([\wÅÄÖåäö]{4,15})/"

Visa signatur

Citera om du vill ha svar :)

Permalänk
Geeks
Jobbar med data

Den här tar a-ö. Och hoppar över @.

/@([a-ö0-9_-]{4,15})/i

Permalänk
Medlem
Skrivet av jreklund:

@BrutalSwede: Den är 6 steg långsammare, annars är det ingen skillnad.

EDIT: Missade att du hade en capture group. Därför 6 steg extra. Annars ingen skillnad.

Lade till en group eftersom jag tänkte att han vill ha ut användarnamnet utan @

Sen beror det väl också på hur man vill att den ska hantera andra skiljetecken som kan dyka upp i en sträng, t.ex om det kommer flera @.

Skrivet av Pelle:

Det där fungerade ypperligt, går det att få så den tar med åäö också? som jag förstått är \w a-zA-Z0-9_?

detta fungerade: "/@([\wÅÄÖåäö]{4,15})/"

Om jag tolkar det korrekt så borde du bara behöva lägga till 'u' som ett alternativ för din regex matchning för att använda unicode. Reserverar mig för att ha fel om det

Visa signatur

| EVGA Z170 FTW | i7 6700k | ASUS RTX 3070 | 16GB DDR4 3200MHz | Cooler Master V850 | Samsung 840 Evo 250GB + 2x WD Black 500GB + Seagate 2TB SSHD + Samsung 970 Evo M.2 1TB|

Permalänk
Geeks
Jobbar med data
Skrivet av BrutalSwede:

Sen beror det väl också på hur man vill att den ska hantera andra skiljetecken som kan dyka upp i en sträng, t.ex om det kommer flera @.

Den biten tänkte jag inte på.

@Pelle:
Personligen tycker jag följande bör lösa alla problem.
Den ignorerar å-ö då den skulle användas inuti en URL. Den accepterar . _ - inuti användarnamnen, så att man kan döpa sig till fornamn.efternamn. Den hoppar även över den sista . ! (etc...), det vill säga allt som inte är en bokstav.
Jag valde just nu att ha minimum 4 tecken och inget slut, men har du max 15 får du såklart lägga in det.
https://regex101.com/r/paN8sq/3

Facebook kör med . i mellan namnen. Här på Sweclockers fungerar det dock inte. De stödjer dock å-ö (och utf-8). Så det är ju en smaksak...
@fornamn.efternamn.
@fornamn-efternamn.
@förnamn-efternam.
@förnamn_efternam.
@fo漢語namn

Sweclockers varianten (med 4 minimum tecken):
https://regex101.com/r/paN8sq/5

Facebook varianten (med 5 minimum tecken):
https://regex101.com/r/paN8sq/6
https://www.facebook.com/help/105399436216001
Facebook tar även bort punkterna från användarnamnen, då de bara finns där för att göra en snyggare separation.

La till Sweclockers exempel.
Permalänk
Medlem
Skrivet av jreklund:

Den biten tänkte jag inte på.

@Pelle:
Personligen tycker jag följande bör lösa alla problem.
Den ignorerar å-ö då den skulle användas inuti en URL. Den accepterar . _ - inuti användarnamnen, så att man kan döpa sig till fornamn.efternamn. Den hoppar även över den sista . ! (etc...), det vill säga allt som inte är en bokstav.
Jag valde just nu att ha minimum 4 tecken och inget slut, men har du max 15 får du såklart lägga in det.
https://regex101.com/r/paN8sq/3

Facebook kör med . i mellan namnen. Här på Sweclockers fungerar det dock inte. De stödjer dock å-ö (och utf-8). Så det är ju en smaksak...
@fornamn.efternamn.
@fornamn-efternamn.
@förnamn-efternam.
@förnamn_efternam.
@fo漢語namn

Sweclockers varianten (med 4 minimum tecken):
https://regex101.com/r/paN8sq/5

Facebook varianten (med 5 minimum tecken):
https://regex101.com/r/paN8sq/6
https://www.facebook.com/help/105399436216001
Facebook tar även bort punkterna från användarnamnen, då de bara finns där för att göra en snyggare separation.

tusen tack! tänkte inte på det där med å-ö om jag ska vara ärlig

Visa signatur

Citera om du vill ha svar :)

Permalänk
Medlem
Citat:

"<div class=\"quote\">$1</div>",
"<a href=\"user.php?profile=$1\">$1</a>"

preg_replace() <3, men regex på HTML?

Beroende på vad slutändamålet är skulle jag rekommendera att kika på DOMXPath nästa gång. Regex är förstås smidigt att implementera men XPath är sannolikt "rätt" verktyg för jobbet och skalar bättre.

Permalänk
Medlem
Skrivet av felplacrd:

preg_replace() <3, men regex på HTML?

Beroende på vad slutändamålet är skulle jag rekommendera att kika på DOMXPath nästa gång. Regex är förstås smidigt att implementera men XPath är sannolikt "rätt" verktyg för jobbet och skalar bättre.

Tack, ska kika på det

Visa signatur

Citera om du vill ha svar :)

Permalänk
Legendarisk
Skrivet av Pelle:

detta fungerade: "/@([\wÅÄÖåäö]{4,15})/"

Här finns en liten fälla som kan vara värd att känna till om du inte redan gör det, men då kanske det kan vara till nytta för någon annan: preg-funktionerna kommer tolka de tecken som ser ut som "åäö" i din editor binärt och beroende på vilken teckenkodning du sparat källfilen med. Om du sparat den med en teckenkodning som bara använder en byte per tecken (t.ex. ISO 8859-1) så är det motsvarande bytes {E5,E4,F6}, men om du nu skickar in en sträng avsedd att tolkas som ISO 8859-7 så kommer den glatt matcha "δεφ".

Men, utbrister du med bestörtning, man ska inte blanda teckenkodningar! — och det är helt riktigt, men många editorer kommer spara källfilen som UTF-8, och nu blir det rikigt spännande: Ett "å" representeras nu av flera bytes, antingen {C3,A5} (å) eller {61,CC,8A} (a + kombinerande ring), beroende på, och när pcre läser detta byte för byte så kommer dit mönster tolkas som att det ska acceptera allt som består av "ord-tecken" (beroende på din locale) samt i värsta fall någon kombination av {61,6F,8A,84,85,88,96,A4,A5,B6,C3,CC}. Dessutom kommer den matcha ofullständiga tecken: Om du har bjudit över dansken på øl (ø = {C3,B8}) så kommer den första byten se giltig ut och inkluderas i träffen, men inte den andra, och din data är nu trasig. Oups

Så, vad är lösningen? Kontrollera vilken teckenkodning du arbetar med (din editor har antagligen någon inställning för det), och sedan:

  • Är det en typ som endast använder en byte per tecken så se till att källfilen och datan använder samma, eller om det inte är möjligt använd ersättningstecken (skriv det tecken i källfilskodningen vars värde motsvarar det i datan) eller skriv in värdet direkt med en escapesekvens.

  • Är det UTF-8 så använd modiferaren "u" för att instruera pcre att behandla både mönster och data som det. Observera att om du använder modifieraren på en sträng som inte är av giltigt format så kommer det orsaka en varning, men om du glömmer det på ett mönster med multibytetecken kommer tyst accepteras, och inte göra vad du avsett... Vanligtvis försöker man använda UTF-8 överallt och blir ditt mönster helt enkelt "/@([\wÅÄÖåäö]{4,15})/u" istället. Mycket väsen för liten ändring alltså.

  • Är det något annat så konvertera till UTF-8.

Visa signatur

Abstractions all the way down.

Permalänk
Legendarisk
Skrivet av jreklund:

Facebook kör med . i mellan namnen. Här på Sweclockers fungerar det dock inte. De stödjer dock å-ö (och utf-8). Så det är ju en smaksak...
@fornamn.efternamn.

@jreklund: Vill inflika att anledningen till att punkter och andra skiljetecken inte inkluderas i namnen är att tolken behöver kunna avgöra var de slutar när de används i vanlig text (precis som att kolonet efter ditt namn utelämnas), och jag har valt att lägga gränsen så här. Man skulle t.ex. kunna fortsätta läsa om tecknet efter punkten är en ny bokstav, men det skulle inte bli perfekt det heller, och det är inget vanligt format på forumet. Det finns dock en del äldre konton som har sådana här specialtecken i sina namn, och för att notififera dessa om svar kan man citera namnet: @"fornamn.efternamn" => @fornamn.efternamn. Skulle namnet innehålla citat-tecken så får man escapa dessa som entities istället... Det görs även automatiskt av svara-knappen.

Visa signatur

Abstractions all the way down.

Permalänk
Legendarisk
Skrivet av jreklund:

Den här tar a-ö. Och hoppar över @.

/@([a-ö0-9_-]{4,15})/i

Det här är också lite farligt. Det kommer i grund och botten från samma problem som inlägget ovan (#17076879), och att en range inte har någon uppfattning om hur just vårat alfabet råkar se ut. Så även om a-ö ser rimligt ut för oss så kommer det tolkas som vilket tecken som helst som råkar ligga mellan hur a (troligen {61}) och ö råkar representeras i din källfilskodning, är den UTF-8 så troligen {C3,B6}), och rangen blir då [\x61-\xC3\xB6], vilket innebär att t.ex. preg_match("/[a-ö]/", "¾") === 1. Observera att det inte hjälper att bara lägga till modifieraren "u" i det här fallet, den kommer fortfarande inkludera allt mellan positionerna för "a" och "ö", fast i UTF-8 istället.

Anledningen till att det (oftast) fungerar med just 0-9, a-z och A-Z är att ASCII designats med dessa i följd, och många teckenkodningar är kompatibla med det:
https://en.wikipedia.org/wiki/ASCII#Character_set

Visa signatur

Abstractions all the way down.

Permalänk
Geeks
Jobbar med data

#17076879: Fungerar lika bra med "/@([\w]{4,15})/u", för åäö är inkluderat inuti utf-8.
#17076898: Självklart måste man hitta sin standard. Jag kör bara med punkter som skiljetecken (och - _ förstås), för att efterlikna vanliga e-postkombinationer/AD-konton.
#17076975: Tack för tipset, alltid lär man sig något nytt. Inte tänkt på att det ligger fler tecken emellan a-ö än a-zåäö. Jag kör dock alltid a-z. Lever lite i den gamla skolan att endast de tecknen "finns" på nätet. Speciellt när man ska använda dem i URLer.

Permalänk
Medlem

Tack för dom utförliga förklaringarna, helt klart värda att tänka på. jag har ändrat så användarnamn endast får innehålla a-z0-9-_ och anpassar allt därefter

Visa signatur

Citera om du vill ha svar :)

Permalänk
Legendarisk
Skrivet av Pelle:

Tack för dom utförliga förklaringarna, helt klart värda att tänka på. jag har ändrat så användarnamn endast får innehålla a-z0-9-_ och anpassar allt därefter

Det är bra att ha för vana att lägga bindestreck som inte ska indikera en range sist i klassen, annars är det lättare att göra ett misstag och skapa en range som tillåter allt mellan 9 och _. Tror att det där bör göra vad du avsett eftersom att det föregående tecknet nu avslutar en annan range, men man får fundera både en och två gånger extra.

Exempel:
https://regex101.com/r/LZpzof/1


@jreklund: Indeed. Livet är mycket trevligare när man kommer undan med ASCII. Ogillar till och med \w eftersom att vilka tecken som inkluderas påverkas av globala inställningar. Ett annat alternativ om man inte vill specifiera alla tillåtna tecken är unicode character properties, men here be dragons.

Visa signatur

Abstractions all the way down.