Regex scripture match

304 views Asked by At

I have the following regex code that i'm trying to perfect for scripture searches. ... are rest of 66 Bible Books.

/(?=\S)\b(genesis|exodus|leviticus|...)(\.)?(\s)?((\d{1,3})([:,-;]?(?=\d))?((\d{1,3})?([:,-;]?(?=\d))?){0,50})/iu

Where I'm running into the issue is that is with multiple passage references like Genesis 3:2 1 Chronicles 2:2 if I use a regex with also a space in search the function assumes that 1 in Chronicles is Genesis 1 and does not recognize it and send it to preg_replace_callback. Any suggestions?

The input is a string that is whole paragraph like

Mat 3:12; Luke 3:17; Revelation 16:14 • gathered, 7 Mat 2:4; Mat 22:34; Mat 27:27; Mar 4:1; Mar 5:21; Joh 11:47; Act 4:26 • into, 1 Revelation 13:10 • resorted, 1 Joh 18:2 • themselves, 1 Act 11:26 • together, 24 Mat 13:2; Mat 22:41; Mat 26:3; Mat 27:17; Mat 27:62; Mar 2:2; Mar 6:30; Mar 7:1; Luke 22:66; Joh 11:52; Act 4:6; Act 4:27; Act 4:31; Act 13:44; Act 14:27; Act 15:6; Act 15:30; Act 20:7; Act 20:8; 1 Corinthians 5:4; Revelation 16:16; Revelation 19:17; Revelation 19:19; Revelation 20:8

what I'm trying to do is make it so that it would match the scripture and passage and then turn it into an a href link using pre_replace_callback function.

1

There are 1 answers

0
Marcos Dimitrio On

In your case, you can use the regex provided by @danielson317 in the comments and extend it to suit your needs. It will even handle "Genesis 3:2 1 Chronicles 2:2" correctly, giving you <a href...>Genesis 3:2</a> <a href...>1 Chronicles 2:2</a>.

You can even make it a class:

<?php
$scriptureUtils = new ScriptureUtils();
echo $scriptureUtils->addLinks($text);

class ScriptureUtils {

    private $booksAbbreviated = array(
        "Gen", "Exo", "Lev", "Num", "Deu", "Jos", "Jud", "Rut", "1 Sam", "2 Sam", "1 Kin", 
        "2 Kin", "1 Chr", "2 Chr", "Ezr", "Neh", "Est", "Job", "Psa", "Pro", "Ecc", "Son", 
        "Isa", "Jer", "Lam", "Eze", "Dan", "Hos", "Joe", "Amo", "Oba", "Jon", "Mic", 
        "Nah", "Hab", "Zep", "Hag", "Zec", "Mal", "Mat", "Mar", "Luk", "Joh", "Act", 
        "Rom", "1 Cor", "2 Cor", "Gal", "Eph", "Phi", "Col", "1 The", "2 The", "1 Tim", 
        "2 Tim", "Tit", "Phi", "Heb", "Jam", "1 Pet", "2 Pet", "1 Joh", "2 Joh", "3 Joh", 
        "Jud", "Rev"
    );

    private $booksFullnames = array(
        "Genesis", "Exodus", "Leviticus", "Numbers", "Deuteronomy", "Joshua", "Judges", 
        "Ruth", "1 Samuel", "2 Samuel", "1 Kings", "2 Kings", "1 Chronicles", 
        "2 Chronicles", "Ezra", "Nehemiah", "Esther", "Job", "Psalms", "Proverbs", 
        "Ecclesiastes", "Song of Solomon", "Isaiah", "Jeremiah", "Lamentations", "Ezekiel", 
        "Daniel", "Hosea", "Joel", "Amos", "Obadiah", "Jonah", "Micah", "Nahum", 
        "Habakkuk", "Zephaniah", "Haggai", "Zechariah", "Malachi", "Matthew", "Mark", 
        "Luke", "John", "Acts", "Romans", "1 Corinthians", "2 Corinthians", "Galatians", 
        "Ephesians", "Philippians", "Colossians", "1 Thessalonians", "2 Thessalonians", 
        "1 Timothy", "2 Timothy", "Titus", "Philemon", "Hebrews", "James", "1 Peter", 
        "2 Peter", "1 John", "2 John", "3 John", "Jude", "Revelation"
    );

    private $addLinkPattern;

    public function __construct() {
        $this->defineLinkPattern();
    }

    public function addLinks($text) {
        $returnString = preg_replace_callback(
            $this->addLinkPattern,
            array($this, "addLinkCallback"),
            $text
        );
        return $returnString;
    }

    private function addLinkCallback($matches) {
        $returnString = "";
        foreach($matches as $match) {
            $returnString .= "<a href=\"bible.php?passage=$match\">$match</a>";
        }
        return $returnString;
    }

    private function defineLinkPattern() {
        // It is important that the full names appear before the abbreviated ones.
        $bookList = implode("|", array_merge($this->booksFullnames, $this->booksAbbreviated));
        $this->addLinkPattern = "/\\b(?:$bookList)(?:\\s+\\d+)?(?::\\d+(?:–\\d+)?(?:,\\s*\\d+(?:–\\d+)?)*)?/";
    }

}