I have a hashtag system: (Note: $body is a variable that is a post that a user submits. The hashtags are in the posts.) I have tried to do this using regex but have found this method to be as equally efficient and a bit easier to follow.
<?php
$string = $body;
$htag = "#";
$arr = explode(" ", $string);
$arrc = count($arr);
$i = 0;
while($i < $arrc) {
if(substr($arr[$i], 0, 1) === $htag) {
$arr[$i] = "<a href = 'category.php?#=$arr[$i]'>".$arr[$i]."</a>";
}
$i++;
}
$string = implode(" ", $arr);
?>
Then, $string is echoed later in the page.
My problem with this is that my method for linking the hashtag to the category page using the php array element. On this page I want to call the word that was "hashtaged" and use a mysql query to get posts that have the hashtags. However, when I call the $arr[$i], to be echoed, I get an error:
Undefined offset: 1 on the line in which I call this array element
into another variable.
Is there any way I can complete this task in a better and more effective way?
Okay, so this can be greatly simplified using some regex and PHP's preg_replace function. #Doge was on the right track, but in my tests, \b didn't quite give the results that I think you want.
Basically, you can replace almost all of what you have with
$newText = preg_replace("/#(\w+)/", "<a href='category.php?tag=$1'>#$1</a>", $text);
As in…
$text = "This is a #hashtag within some #awesometext.";
$newText = preg_replace("/#(\w+)/", "<a href='category.php?tag=$1'>#$1</a>", $text);
echo $newText;
The result of this would be…
This is a <a href='category.php?tag=hashtag'>#hashtag</a> within some <a href='category.php?tag=awesometext'>#awesometext</a>.
See it in action here
Related
I'm working on a bb-code replacement function when a user wants to post a smiley.
The problem is, that if someone uses a bb-code smiley that doesn't exists, it results in an empty post because the browser will not display the (non-existing) emoticon.
Here's my code so far:
// DO [:smiley:]
$convert_smiley = preg_match_all('/\[:(.*?):\]/i', $string, $matches);
if( $convert_smiley )
{
$string = preg_replace('/\[:(.*?):\]/i', "<i class='icon-smiley-$1'></i>", $string, $convert_smiley);
}
return $string;
The bb-code for a smiley usually looks like [:smile:] or like [:sad:] or like [:happy:] and so on.
The code above is working well, until someone post a bb-code that doesn't exists, so what I am asking for is a fix for non existing smileys.
Is there a possibility, in example to create an array, like array('smile', 'sad', 'happy') and only bb-code that matches one or more in this array will be converted?
So, after the fix, posting [:test:] or just [::] should not be converted and should be posted as original text while [:happy:] will be converted.
Any ideas? Thanks!
I put your possible smiley’s in non-grouping parentheses with or symbol in a regexp:
<?php
$string = 'looks like [:smile:] or like [:sad:] or like [:happy:] [:bad-smiley:]';
$string = preg_replace('/\[:((?:smile)|(?:sad)|(?:happy)):\]/i', "<i class='icon-smiley-$1'></i>", $string);
print $string;
Output:
looks like <i class='icon-smiley-smile'></i> or like <i class='icon-smiley-sad'></i> or like <i class='icon-smiley-happy'></i> [:bad-smiley:]
[:bad-smiley:] is ignored.
A simple workaround:
$string ="[:clap:]";
$convert_smiley = preg_match_all('/\[:(.*?):\]/i', $string, $matches);
$emoticons = array("smile","clap","sad"); //array of supported smileys
if(in_array($matches[1][0],$emoticons)){
//smily exists
$string = preg_replace('/\[:(.*?):\]/i', "<i class='icon-smiley-$1'></i>", $string, $convert_smiley);
}
else{
//smily doesn't exist
}
Well, the first issue is you are setting $convert_smiley to the true/false value of the preg_match_all() instead of parsing the results. Here is how I reworked your code:
// Test strings.
$string = ' [:happy:] [:frown:] [:smile:] [:foobar:]';
// Set a list of valid smileys.
$valid_smileys = array('smile', 'sad', 'happy');
// Do a `preg_match_all` against the smiley’s
preg_match_all('/\[:(.*?):\]/i', $string, $matches);
// Check if there are matches.
if (count($matches) > 0) {
// Loop through the results
foreach ($matches[1] as $smiley_value) {
// Validate them against the valid smiley list.
$pattern = $replacement = '';
if (in_array($smiley_value, $valid_smileys)) {
$pattern = sprintf('/\[:%s:\]/i', $smiley_value);
$replacement = sprintf("<i class='icon-smiley-%s'></i>", $smiley_value);
$string = preg_replace($pattern, $replacement, $string);
}
}
}
echo 'Test Output:';
echo htmlentities($string);
Just note that I chose to use sprintf() for the formatting of content & set $pattern and $replacement as variables. I also chose to use htmlentities() so the HTML DOM elements can easily be read for debugging.
I need to neatly output spun text in a php page.
I already have the prespun text in {hi|hello|greetings} format.
I have a php code that i found elsewhere, but it does not output the spun text on sentence level, where two {{ come.
Here is the code that needs fixing.
<?php
function spinText($text){
$test = preg_match_all("#\{(.*?)\}#", $text, $out);
if (!$test) return $text;
$toFind = Array();
$toReplace = Array();
foreach($out[0] AS $id => $match){
$choices = explode("|", $out[1][$id]);
$toFind[]=$match;
$toReplace[]=trim($choices[rand(0, count($choices)-1)]);
}
return str_replace($toFind, $toReplace, $text);
}
echo spinText("{Hello|Hi|Greetings}!");;
?>
The output will be randomly chose word: Hello OR Hi OR Greetings.
However, if there is a sentence level spinning, the output is messed up.
E.g.:
{{hello|hi}.{how're|how are} you|{How's|How is} it going}
The output is
{hello.how're you|How is it going}
As you can see the text has not been spun completely.
Thank you
This is a recursive problem, so regular expressions aren't that great; but recursive patterns can help though:
function bla($s)
{
// first off, find the curly brace patterns (those that are properly balanced)
if (preg_match_all('#\{(((?>[^{}]+)|(?R))*)\}#', $s, $matches, PREG_OFFSET_CAPTURE)) {
// go through the string in reverse order and replace the sections
for ($i = count($matches[0]) - 1; $i >= 0; --$i) {
// we recurse into this function here
$s = substr_replace($s, bla($matches[1][$i][0]), $matches[0][$i][1], strlen($matches[0][$i][0]));
}
}
// once we're done, it should be safe to split on the pipe character
$choices = explode('|', $s);
return $choices[array_rand($choices)];
}
echo bla("{{hello|hi}.{how're|how are} you|{How's|How is} it going}"), "\n";
See also: Recursive patterns
here's the line of code that I came up with:
function Count($text)
{
$WordCount = str_word_count($text);
$TextToArray = explode(" ", $text);
$TextToArray2 = explode(" ", $text);
for($i=0; $i<$WordCount; $i++)
{
$count = substr_count($TextToArray2[$i], $text);
}
echo "Number of {$TextToArray2[$i]} is {$count}";
}
So, what's gonna happen here is that, the user will be entering a text, sentence or paragraph. By using substr_count, I would like to know the number of occurrences of the word inside the array. Unfortunately, the output the is not what I really need. Any suggestions?
I assume that you want an array with the word frequencies.
First off, convert the string to lowercase and remove all punctuation from the text. This way you won't get entries for "But", "but", and "but," but rather just "but" with 3 or more uses.
Second, use str_word_count with a second argument of 2 as Mark Baker says to get a list of words in the text. This will probably be more efficient than my suggestion of preg_split.
Then walk the array and increment the value of the word by one.
foreach($words as $word)
$output[$word] = isset($output[$word]) ? $output[$word] + 1 : 1;
If I had understood your question correctly this should also solve your problem
function Count($text) {
$TextToArray = explode(" ", $text); // get all space separated words
foreach($TextToArray as $needle) {
$count = substr_count($text, $needle); // Get count of a word in the whole text
echo "$needle has occured $count times in the text";
}
}
$WordCounts = array_count_values(str_word_count(strtolower($text),2));
var_dump($WordCounts);
I'm trying to scrape images from the mark-up of certain webpages. These webpages all have a slideshow. Their sources are contained in javascript objects on the page. I'm thinking i need to get_file_contents("http://www.example.com/page/1"); and then have a preg_match_all() function that i can input a phrase(ie. "\"LargeUrl\":\"", or "\"Description\":\"") and get the string of characters until it hits the next quotation mark it finds.
var photos = {};
photos['photo-391094'] = {"LargeUrl": "http://www.example.org/images/1.png","Description":"blah blah balh"};
photos['photo-391095'] = {"LargeUrl": "http://www.example.org/images/2.png","Description":"blah blah balh"};
photos['photo-391096'] = {"LargeUrl": "http://www.example.org/images/3.png","Description":"blah blah balh"};
I have this function, but it returns the entire line after the input phrase. How can i modify it to look for whatever's after the input phrase up until it hits the next quotation mark it finds? Or am i doing this all wrong and there's a better way?
$page = file_get_contents("http://www.example.org/page/1");
$word = "\"LargeUrl\":\"";
if(preg_match_all("/(?<=$word)\S+/i", $page, $matches))
{
echo "<pre>";
print_r($matches);
echo "</pre>";
}
Ideally the function would return a an array like the following if i inputed "\"LargeUrl\":\""
$matches[0] = "http://www.example.org/images/1.png";
$matches[1] = "http://www.example.org/images/2.png";
$matches[2] = "http://www.example.org/images/3.png";
You can use parenthesis to capture the parts you're interested in. A simple regex to do it is
$word = '"LargeUrl":';
$pattern = "$word" . '\s+"([^"]+)"';
preg_match_all("/$pattern/", $page, $matches);
print_r($matches[1]);
There is definitely a regex that will match each image URL, but you could also, if its easier for you, match the whole object and then json_decode() the matched string
I have perfect solution for you....use the following code and you will get your needed result.
preg_match_all('/{"LargeUrl":(.*?)"(.*?)"/', $page, $result, PREG_PATTERN_ORDER);
for ($i = 0; $i < count($result[0]); $i++) {
echo "<pre>";
echo $result[2][$i];
echo "</pre>";
}
Thanks......p2c
$str='<p>http://domain.com/1.html?u=1234576</p><p>http://domain.com/2.html?u=2345678</p><p>http://domain.com/3.html?u=3456789</p><p>http://domain.com/4.html?u=56789</p>';
$str = preg_replace('/.html\?(.*?)/','.html',$str);
echo $str;
I need get
<p>http://domain.com/1.html</p>
<p>http://domain.com/2.html</p>
<p>http://domain.com/3.html</p>
<p>http://domain.com/4.html</p>
remove ?u=*number* from every words last part. thanks.
Change this line:
$str = preg_replace('/.html\?(.*?)/','.html',$str);
into this:
$str = preg_replace('/.html\?(.*?)</','.html<',$str);
An alternative to the other answers:
preg_replace("/<p>([^?]*)\?[^<]*<\/p>/", "<p>$1</p>", $input);
This will match all types of urls with url variables, not only the ones with html-files in them.
For example, you can also extract these types of values:
<p>http://domain.com/1.php?u=1234576</p>
<p>http://domain.com?u=1234576</p>
<p>http://domain.com</p>
<p>http://domain.com/pages/users?uid=123</p>
With an output of:
<p>http://domain.com/1.php</p>
<p>http://domain.com</p>
<p>http://domain.com</p>
<p>http://domain.com/pages/users</p>
This code will load the url's into an array so they can be handled on the fly:
$str = '<p>http://domain.com/1.html?u=1234576</p><p>http://domain.com/2.html?u=2345678</p><p>http://domain.com/3.html?u=3456789</p><p>http://domain.com/4.html?u=56789</p>';
$str = str_replace("<p>","",$str);
$links = preg_split('`\?.*?</p>`', $str,-1,PREG_SPLIT_NO_EMPTY);
foreach($links as $v) {
echo "<p>".$v."</p>";
}