1
<?php

$string="Hello how are ##you ? I want ##join you.";

echo $string;

// now I want replace all ##.... words with <a>##.....</a>
// example Hello how are <a>##you</a> ? I want <a>##join</a>you.

?>

Now I want replace all ##.... words with ##..... example Hello how are ##you ? I want ##join you.

1 Answers1

3

I'll let others go for regex solutions. I'll propose something that hopefully more readable.

The following code uses my Parser class from Paladio (it's under CC-BY 3.0), it works on UTF-8.

The code is explained in the comments:

<?php
    $string = "Hello how are ##you ? I want ##join you.";

    // now I want replace all ##.... words with <a>##.....</a>

    //Create a parser object for the string
    $parser = new Parser($string);

    //Create a variable to hold the result
    $result = '';

    //While we haven't reached the end of the string
    while($parser->CanConsume())
    {
        //Take all the text until the next '##' or the end of the string
        // and add to the result the string taken
        $result .= $parser->ConsumeUntil('##');
        //If we take a '##'
        if ($parser->Consume('##'))
        {
            //Take the text until the next whitespace or new line
            $tag = $parser->ConsumeUntil(array(' ', "\t", "\r", "\n"));
            //Add the new converted text to the result
            $result .= '<a>###'.$tag.'</a>';
        }
    }

    // example Hello how are <a>##you</a> ? I want <a>##join</a>you.
    echo $result;
?>

Based on the comments, this is a modified version that will allow to detect words marked with any of the given strings ('##' and '**' in the example):

function autolink($ptext, $detc)
{
    // declared whitespace for readability and performance
    $whitespace = array(' ', "\t", "\r", "\n");
    $parser = new Parser($ptext);
    $result = '';
    while($parser->CanConsume())
    {
        $result .= $parser->ConsumeUntil($detc);
        if ($parser->Consume($detc))
        {
            $newtag = $parser->ConsumeUntil($whitespace);
            $result .= '<a href='.$newtag.'>'.$newtag.'</a>';
        }
    }
    return $result;
}

Example usage:

echo autolink("Hello how are ##you ? I want **join you.", array('##', '**'));

Outputs:

Hello how are <a href=you>you</a> ? I want <a href=join>join</a> you.

Tested on my local server.


Notes:

  1. The instruction $parser->Consume($detc) will return the found string, so you can use it to branch, example:

    $input = $parser->Consume(array('a', 'b')); if ($input === 'a') { // do something } else if ($input === 'b') { // do something else } else /if ($input === null)/ { // fallback case }

  2. The supported things to Consume are:

  1. Given strings.
  2. Arrays of strings.
  3. Numbers (amount of characters).
  4. Null (will consume a single character).
  1. Parser uses mb_* functions for some of the operations^, and expects UTF-8. If you experience problems with encoding you want to call mb_internal_encoding('UTF-8'); before using Parser and convert your string to UTF-8 (I recommend iconv for this operation). ^: Some other parts are optimized using byte per byte operations.
Theraot
  • 18,248
  • 4
  • 45
  • 72
  • 1
    @EthicalRajesh glad of being of help. As mentioned, I'm the author of this library, feel free to make suggestions, and please report any problems. Cheers! – Theraot Dec 24 '13 at 20:14
  • Thanks so much I will use it on www.rdtcportal.com [Articles Section] – Ethical Rajesh Dec 24 '13 at 20:17
  • Thanks so much I working fine for ##. Is possible that I can detect two strings like ## and ** together without call two times? – Ethical Rajesh Dec 25 '13 at 11:40
  • I try with its but failed. function autolink($ptext,$detc) { include_once("includes/class/autolink.class.php"); $newword = array_unique(explode(',',$detc)); foreach ($newword as $key => $oldtag) { $oldtag = trim($oldtag); $parser = new Parser($ptext); $result = ''; while($parser->CanConsume()) { $result .= $parser->ConsumeUntil($oldtag); if ($parser->Consume($oldtag)) {$newtag = $parser->ConsumeUntil(array(' ', "\t", "\r", "\n")); $result .= "$newtag";}} } return $result;} ####################### autolink($mytext,'##,**'); – Ethical Rajesh Dec 25 '13 at 12:10
  • 1
    @EthicalRajesh yes, you can detect two strings in a single call, just pass an array to `Consume` instead of a string. `Consume` will return the string that found. I have updated my answer. – Theraot Dec 25 '13 at 17:00
  • Sir, please please explain note 1 with example like function autolink example. Thanks Last question :) – Ethical Rajesh Dec 31 '13 at 22:07
  • 1
    My answer already has some code in the notes, so I guess what you want is a use case. Maybe the one at [How to write a recursive regex that matches nested parentheses?](http://stackoverflow.com/a/20570533/402022) can help you, there I use it to check for "(" or ")". Other than that, tell me what are you tring to do. – Theraot Jan 01 '14 at 07:58