regex, delimiters

Any questions involving matching text strings to patterns - the pattern is called a "regular expression."

Moderator: General Moderators

Post Reply
jonathant
Forum Commoner
Posts: 32
Joined: Sat Jan 07, 2006 3:13 pm

regex, delimiters

Post by jonathant »

I have a textbox that will be used to create fill-in-the-blank questions. I want the users to be able to denote the words to be blanked out by setting a delimiter like "**" or something. What is the best way to extract the delimited words and place them into an array? Also, I'd like to change the question string to substitute an underscore in place of the phrase. I'm thinking two different regular expressions will be the way to go, but I'm really weak with them so any help would be greatly appreciated. You guys and gals are great!

Code: Select all

This is an **example** fill-in-the-blank **question**?

Code: Select all

// I need the array to look like:
array ('example', 'question');

// and the question string to look like:
"This is an _ fill-in-the-blank _?"
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

How about you output a paragraph of text with <input type="text">s wherever you have a blank to fill in instead.
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Post by Ambush Commander »

Agreed.
jonathant
Forum Commoner
Posts: 32
Joined: Sat Jan 07, 2006 3:13 pm

Post by jonathant »

ole wrote:How about you output a paragraph of text with <input type="text">s wherever you have a blank to fill in instead.
That's what I planned on doing. I just threw out the underscore as an example. What about finding the words in the first place?

Code: Select all

$string = "This is the **example** string that was taken from the **question** create form.";

preg_match('(**)', $string, $blanks);

echo "The words are: <br>";

foreach ($blanks as $word) {
     echo $word."<br>";
}
I have no idea how to get the extract the words between the **.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

"*" is a metacharacter. If you want to match the character, it must be escaped.

The solution to finding text between two given elements has been talked about quite a few times around here. Please search.
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

Where is any finding required? The data comes to you in $_POST as a nice associative array.
jonathant
Forum Commoner
Posts: 32
Joined: Sat Jan 07, 2006 3:13 pm

Post by jonathant »

Maybe this isn't a regular expression problem at all. Let's say I want to turn this:
This is an {example} question. It could be {fairly long} with multiple {blanks}.
Into this (name and id tags left out for abbreviation).
This is an <input type="text" /> question. It could be <input type="text" /> with multiple <input type="text" />.
Here's what I've got so far, that isn't working.

Code: Select all

// $question = Array ( [id] => 7 [question] => An {example} question. [sequence] => 6 [type] => fb )

if ($question['type'] == 'fb') {
                // convert string
                $pos=0;
                $open_positions=array();
                while (strpos($question['question'], "{", $pos)) {
                    $open_positions[]=strpos($question['question'], "{", $pos);
                    $pos=strpos($question['question'], "{", $pos) + 1;
                }
                
                $pos=0;
                $closed_positions=array();
                while (strpos($question['question'], "}", $pos)) {
                    $closed_positions[]=strpos($question['question'], "}", $pos);
                    $pos=strpos($question['question'], "}", $pos) + 1;
                }
                
                if (count($open_positions) != count($closed_positions)) {
                    return FALSE;
                }
                
                $positions=array_merge($open_positions, $closed_positions);
                sort($positions);
                
                $counter=0;
                $wordcount=1;
                $new_question=$question['question'];
                while (count($positions) > $counter) {
                    if ($counter == 0) {
                        $length = $positions[$counter + 1] - $positions[$counter] - 2;
                    } else {
line 132                         $length = $positions[$counter + 1] - $positions[$counter] - 1;
                    }
                    $replace="<input type=\"text\" id=\"word_".$wordcount."\" name=\"word_".$wordcount."\" /></input>";
                    substr_replace($new_question, $replace ,$positions[$counter], $length);
                    $counter = $counter + 1;
                    $wordcount = $wordcount + 1;
                }
                
                $prepared_questions[]=array('id' => $question['id'], 'question' => $new_question,
                    'sequence' => $question['sequence'], 'type' => $question['type']);
            }
A PHP Error was encountered
Severity: Notice
Message: Undefined offset: 2
Filename: student/take_test.php
Line Number: 132
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

That's a whole lot of code. You must want to start off with

Code: Select all

$str = preg_replace('~\b\{[^\}]+\}\b~', '<input type="text" />', $str);
and go from there.

edit: forgot to escape some stuff
Last edited by Ollie Saunders on Sun Jan 14, 2007 11:42 am, edited 2 times in total.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

The following may work better in the end.

Code: Select all

<?php

$str = 'This is an {example} question. It could be {fairly long} with multiple {blanks}.';

function fixName($a)
{
	return '<input type="text" name="' . preg_replace('#[^a-z0-9]#i', '_', $a[1]) . '" />';
}

$newstr = preg_replace_callback('#\{([a-z0-9 -]+)\}#i', 'fixName', $str);
echo $str, PHP_EOL, $newstr;

?>

Code: Select all

This is an {example} question. It could be {fairly long} with multiple {blanks}.
This is an <input type="text" name="example" /> question. It could be <input type="text" name="fairly_long" /> with multiple <input type="text" name="blanks" />.
jonathant
Forum Commoner
Posts: 32
Joined: Sat Jan 07, 2006 3:13 pm

Post by jonathant »

Thanks for the help! I ended up using feyd's solution which was only slightly less code than my own :)
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

Yeah feyd's was more complete than mine.
Which is unusual; feyd is usually a man of few words or, in this case, variables.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

ole wrote:Which is unusual; feyd is usually a man of few words or, in this case, variables.
:D
Post Reply