Προς το περιεχόμενο

Regular expression και preg_match (PHP)


Προτεινόμενες αναρτήσεις

Δημοσ. (επεξεργασμένο)

Έχουμε το εξής τμήμα κώδικα που εντοπίζει αν κάποιος χρήστης προσπαθεί να στείλει προσωπικό μήνυμα στο σύστημα Chat με την εντολή /pm η οποία συντάσσεται ως εξής:

/pm {username or userid} ; {message}

(χωρίς τις αγκύλες)

 

Σας παραθέτω τον κώδικα:

        if (preg_match("#^(/pm\s+)(.+?[^;]);(.+?)$#i", $message, $matches))
        {               
            $this->doshout = false;
           
            $user = htmlspecialchars_uni(addslashes(trim($matches[2])));
            $user = addslashes(convert_urlencoded_unicode($user));
            if ($pmuser = $this->vbulletin->db->query_first("select userid, username from " . TABLE_PREFIX . "user where userid='$user' or username='$user'"))
            {
                $this->doshout = true;
                $this->private = $pmuser['userid'];
                $message = trim($matches[3]);
            }
        }
Υπάρχει όμως το εξής πρόβλημα: αν το {message} είναι κείμενο πολλών γραμμών (πχ από copy/paste), τότε δεν περνάει τον έλεγχο της preg_match το μήνυμα και αντί να πάει σε pm, δημοσιεύεται στο κεντρικό chat (για να σας βάλω στο πρόβλημα).

Πως μπορώ να το διορθώσω; Έχω μια δυσκολία με τις regular expressions. :-)

 

Ευχαριστώ!

Επεξ/σία από philos
Δημοσ.

Πρώτα δυο λόγια γι' αυτό που ήδη έχεις.
 
#^(/pm\s+)(.+?[^;]);(.+?)$#i

 

Στο πράσινο δε χρειάζεσαι παρενθέσεις γιατί δε σ' ενδιαφέρει να κάνεις capture. Αν κάνει match τότε ξέρεις πως πρόκειται για πμ έτσι κι αλλιώς. Οπότε γίνεται /pm\s+

 

Στο μπλε ζητάς ένα ή περισσότερους χαρακτήρες και μετά κάτι που δεν είναι ερωτηματικό. Αυτό πρώτον δεν έχει πολύ νόημα -- το φορσάρεις να μην τελειώνει σε δύο ερωτηματικά, αλλά ποιός ο λόγος από τη στιγμή που επιτρέπεις δύο ερωτηματικά νωρίτερα; Κατά τη γνώμη μου θα έπρεπε να είναι απλώς (.+?)

 

Στο κόκκινο σου έχει μείνει "από συνήθεια" το nongreedy quantifier αλλά δεν έχει νόημα μιας και αμέσως μετά ακολουθεί unconditional τέλος εισόδου. Θα έπρεπε να είναι απλώς (.+) και πριν από αυτό καλύτερα βάλε και \s* για να φάει τα τυχόν extra spaces.

 

Τώρα όσον αφορά αυτό που ρώτησες, το πρόβλημά σου είναι ότι το . κάνει match οποιοδήποτε χαρακτήρα εκτός από newline. Επομένως το κόκκινο pattern σταματάει πριν το πρώτο newline και επειδή εκεί που σταματάει δεν ακολουθεί το τέλος του string αποτυγχάνει το match συνολικά.

 

Εσύ θέλεις και τα newlines, επομένως το μόνο που έχεις να κάνεις είναι να βάλεις και το s modifier στο τέλος:

 

#/pm\s+(.+?);\s*(.+)$#si

  • Like 1
Δημοσ.

δεν το έχω πολύ με τις κανονικές εκφράσεις αλλά φαντάζομαι ότι το πρόβλημά της θα είναι με τους χαρακτήρες αλλαγής γραμμής, αν δοκίμαζες ένα trim() στο message πριν την if σου;;

Δημοσ.

Πρώτα δυο λόγια γι' αυτό που ήδη έχεις.

 

#^(/pm\s+)(.+?[^;]);(.+?)$#i

 

Στο πράσινο δε χρειάζεσαι παρενθέσεις γιατί δε σ' ενδιαφέρει να κάνεις capture. Αν κάνει match τότε ξέρεις πως πρόκειται για πμ έτσι κι αλλιώς. Οπότε γίνεται /pm\s+

 

Στο μπλε ζητάς ένα ή περισσότερους χαρακτήρες και μετά κάτι που δεν είναι ερωτηματικό. Αυτό πρώτον δεν έχει πολύ νόημα -- το φορσάρεις να μην τελειώνει σε δύο ερωτηματικά, αλλά ποιός ο λόγος από τη στιγμή που επιτρέπεις δύο ερωτηματικά νωρίτερα; Κατά τη γνώμη μου θα έπρεπε να είναι απλώς (.+?)

 

Στο κόκκινο σου έχει μείνει "από συνήθεια" το nongreedy quantifier αλλά δεν έχει νόημα μιας και αμέσως μετά ακολουθεί unconditional τέλος εισόδου. Θα έπρεπε να είναι απλώς (.+) και πριν από αυτό καλύτερα βάλε και \s* για να φάει τα τυχόν extra spaces.

 

Τώρα όσον αφορά αυτό που ρώτησες, το πρόβλημά σου είναι ότι το . κάνει match οποιοδήποτε χαρακτήρα εκτός από newline. Επομένως το κόκκινο pattern σταματάει πριν το πρώτο newline και επειδή εκεί που σταματάει δεν ακολουθεί το τέλος του string αποτυγχάνει το match συνολικά.

 

Εσύ θέλεις και τα newlines, επομένως το μόνο που έχεις να κάνεις είναι να βάλεις και το s modifier στο τέλος:

 

#/pm\s+(.+?);\s*(.+)$#si

 

Λείπει ένα \ στην αρχή (\/pm..) αλλά εξαιρετική απάντηση.  :-)  

Δημοσ.

Λείπει ένα \ στην αρχή (\/pm..) αλλά εξαιρετική απάντηση.  :-)  

 

Δε χρειάζεται επειδή χρησιμοποιεί το # σαν delimiter  :)

  • Like 1

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...