How to echo only a part of preg_replace string? - php

I've searched but there's nothing that really helps. I'm learning PHP and trying to output the value of $1, after preg_replace has applied the regex rules.
I only want to be left with <span>$1</span>, and the rest of the string needs stripping. Note that the string is highly variable so I can't set custom strstr for example to remove the word 'Get' as there are many variations.
$the_coupon_title = 'Get 10% off at Walmart';
$the_coupon_title = preg_replace(
'/((£\d+\.?\d{0,2}|\d+\.?\d{0,2}%)\s+(off)+)/i',
'<span>$1</span>',
$the_coupon_title
);
echo $the_coupon_title;
?>

You can extract the match and wrap with span tag:
$the_coupon_title = 'Get 10% off at Walmart';
$the_coupon_title = preg_match(
'/(£)?\d+(?:\.\d{1,2})?(?(1)|%)\s+off/iu',
$the_coupon_title,
$m
);
echo '<span>', htmlspecialchars($m[0], ENT_QUOTES | ENT_HTML5), '</span>';
See the PHP demo. New regex details:
(£)? - An optional group #1: a £ char
\d+(?:\.\d{1,2})? - one or more digits and then an optional sequence of . and one or two digits
(?(1)|%) - if £ was not captured in Group 1 match % here
\s+off - one or more whitespaces and off string.
Another approach is to match any text up to the pattern of yours, capture the value matched with the pattern, and then match the rest of the string and replace the match with the captured substring:
echo preg_replace(
'/^.*?((£)?\d+(?:\.\d{1,2})?(?(2)|%)\s+off).*/iu',
'<span>$1</span>',
$the_coupon_title);
See another PHP demo. Note the \1 to \2 change since now the pound symbol is captured into Group 2. It is also prone to HTML injection.

Related

simple pattern with preg_match_ALL work fine!, how to use with preg_replace?

thanks by your help.
my target is use preg_replace + pattern for remove very sample strings.
then only using preg_replace in this string or others, I need remove ANY content into <tag and next symbol >, the pattern is so simple, then:
$x = '#<\w+(\s+[^>]*)>#is';
$s = 'DATA<td class="td1">111</td><td class="td2">222</td>DATA';
preg_match_all($x, $s, $Q);
print_r($Q[1]);
[1] => Array
(
[0] => class="td1"
[1] => class="td2"
)
work greath!
now I try remove strings using the same pattern:
$new_string = '';
$Q = preg_replace($x, "\\1$new_string", $s);
print_r($Q);
result is completely different.
what is bad in my use of preg_replace?
using only preg_replace() how I can remove this strings?
(we can use foreach(...) for remove each string, but where is the error in my code?)
my result expected when I intro this value:
$s = 'DATA<td class="td1">111</td><td class="td2">222</td>DATA';
is this output:
$Q = 'DATA<td>111</td><td>222</td>DATA';
Let's break down your RegEx, #<\w+(\s+[^>]*)>#is, and see if that helps.
# // Start delimiter
< // Literal `<` character
\w+ // One or more word-characters, a-z, A-Z, 0-9 or _
( // Start capturing group
\s+ // One or more spaces
[^>]* // Zero or more characters that are not the literal `>`
) // End capturing group
> // Literal `>` character
# // End delimiter
is // Ignore case and `.` matches all characters including newline
Given the input DATA<td class="td1">DATA this matches <td class="td1"> and captures class="td1". The difference between match and capture is very important.
When you use preg_match you'll see the entire match at index 0, and any subsequent captures at incrementing indexes.
When you use preg_replace the entire match will be replaced. You can use the captures, if you so choose, but you are replacing the match.
I'm going to say that again: whatever you pass as the replacement string will replace the entirety of the found match. If you say $1 or \\=1, you are saying replace the entire match with just the capture.
Going back to the sample after the breakdown, using $1 is the equivalent of calling:
str_replace('<td class="td1">', ' class="td1"', $string);
which you can see here: https://3v4l.org/ZkPFb
To your question "how to change [0] by $new_string", you are doing it correctly, it is your RegEx itself that is wrong. To do what you are trying to do, your pattern must capture the tag itself so that you can say "replace the HTML tag with all of the attributes with just the tag".
As one of my comments noted, this is where you'd invert the capturing. You aren't interesting in capturing the attributes, you are throwing those away. Instead, you are interested in capturing the tag itself:
$string = 'DATA<td class="td1">DATA';
$pattern = '#<(\w+)\s+[^>]*>#is';
echo preg_replace($pattern, '<$1>', $string);
Demo: https://3v4l.org/oIW7d

How to add spaces when a number is followed by a letter in laravel

I have this text in UTF-8
名古屋市北区,大曽根3丁目 13-2V-
as you can see, in 根3丁 there are no spaces, I would like it to end up being 根 3 丁 for example, the same with -2V and add spaces: - 2 V
As a final result, I am looking for the text to be
名古屋市北区,大曽根 3 丁目 13- 2 V-
that is, adding spaces while there are no numbers next to it (for example that 13-, it must remain the same)
what I currently have removes all the numbers and adds a space to them
$string = preg_replace('/\d+/u', ' ', $string);
You can use groups in your regex pattern replacement.
Group 1: (\p{L}|\-). Any letter or -
Group 2: (\d+). Any number(s)
Group 3: (\p{L}|\-). Any letter or -
$string = preg_replace(
'/(\p{L}|\-)(\d+)(\p{L}|\-)/u', /* pattern */
'${1} ${2} ${3}', /* replacement */
$string /* subject */
);
You could assert either a letter or _ to the left and right of the digits, and replace with the full match surrounded by a space on both sides.
(?<=[-\p{L}])\d+(?=[\p{L}-])
Regex demo
Example
$s = "名古屋市北区,大曽根3丁目 13-2V-";
$pattern = "/(?<=[-\p{L}])\d+(?=[\p{L}-])/u";
echo preg_replace($pattern, " $0 ", $s);
Output
名古屋市北区,大曽根 3 丁目 13- 2 V-

Php select from string

Hi I'm new to php and I need a little help
I need to change the text that is between ** in php string and put it between html tag
$text = "this is an *example*";
But I really don't know how and i need help
personally I would use explode, you can then piece the sentence back together if the example appears in the middle of a sentence
<?php
$text = "this is an *example*";
$pieces = explode("*", $text);
echo $pieces[0];
?>
Edit:
Since you're looking for what basically amounts to custom BB Code use this
$text = "this is an *example*";
$find = '~[\*](.*?)[\*]~s';
$replace = '<span style="color: green">$1</span>';
echo preg_replace($find,$replace,$text);
You can add this to a function and have it parse any text that gets passed to it, you can also make the find and replace variables into arrays and add more codes to it
You really should use a DOM parser for things like this, but if you can guaratee it will always be the * character you can use some regex:
$text = "this is an *example*";
$regex = '/(?<=\*)(.*?)(?=\*)/';
$replacement = 'ostrich';
$new_text = preg_replace($regex, $replacement, $text);
echo $new_text;
Returns
this is an *ostrich*
Here is how the regex works:
Positive Lookbehind (?<=\*)
\* matches the character * literally (case sensitive)
1st Capturing Group (.*?)
.*? matches any character (except for line terminators)
*? Quantifier — Matches between zero and unlimited times, as few times as possible, expanding as needed (lazy)
Positive Lookahead (?=\*)
\* matches the character * literally (case sensitive)
This regex essentially starts and ends by looking at what is ahead of and behind the search character you specified and leaves those characters intact during the replacement with preg_replace().

PHP Find All Hashtags But No In Link

i need to find all hashtags in string but not on link example:
#q https://www.youtube.com/watch?v=#Vmyx7cyZcKU #q1 #q3 [ I Want to Get only #q, #q1, #q not hashtags in link ]
my code:
$string = "#q https://www.youtube.com/watch?v=#Vmyx7cyZcKU #q1 #q3";
// Link
$string = preg_replace("!(((f|ht)tp(s)?://)[-a-zA-Zа-яА-Я()0-9#:%_+.~#?&;//=]+)!i", "<a href='$1' target='_blank'>$1</a>", $string);
// Hashtag
$hashtag_url = $web_url. "hashtag/\\0";
$string = preg_replace("(\s?#\w+)", "<a href='$hashtag_url'>\\0</a>", $string);
See Image What My Code Show !!!
http://i.stack.imgur.com/p8IyE.png
Match all the hashtags outside the URL can be achieved with a regex that matches URLs and discards them, and then matches hastags in all other contexts:
'~(?:f|ht)tps?://[-a-zA-Zа-яА-Я()0-9#:%_+.\~#?&;/=]+(*SKIP)(*F)|#(\w+)~'
See the regex demo
PHP demo:
$string = "#q https://www.youtube.com/watch?v=#Vmyx7cyZcKU #q1 #q3";
$string = preg_replace("!(?:f|ht)tps?://[-a-zA-Zа-яА-Я()0-9#:%_+.~#?&;/=]+(*SKIP)(*F)|#(\w+)!", "<a href='$1'>$0</a>", $string);
echo $string;
Feel free to adjust (especially the replacement pattern) as per your needs.
Details:
(?:f|ht)tps?://[-a-zA-Zа-яА-Я()0-9#:%_+.\~#?&;/=]+ - the URL matching part (taken from your code)
(*SKIP)(*F) - PCRE verbs omitting the match and proceeding to the next match from the current index
| - or
#(\w+) - a # followed with 1 or more word chars.
To enable \w to match Unicode letters, too, add ~u modifier at the end.

Regular expression to extract data from a colum and put it in another column

I have a MySQL table with few columns.
Column 1 contains html code:
<p style="xxx"><img src="path/to/file.png(or jpg)"></p>
I want to extract the src (path/file.xxx) to column 2, and then remove the whole P tag from column 1.
I tried few techniques like
preg_match('/\< *[img][^\>]*[src] *= *[\"\']{0,1}([^\"\']*)/i', $row->image, $matches);
But nothing seems to work.
Anything simple and light to use?
[] represents a character set, not a sequence of a characters.
$html = '<p style="xxx"><img src="path/to/file.png(or jpg)"></p>';
preg_match('/<img src="([^"]*)">/', $html, $m);
echo $m[0] . "\n";
echo $m[1] . "\n";
outputs:
<img src="path/to/file.png(or jpg)">
path/to/file.png(or jpg)
With all the disclaimers about using regex to handle html, you can use a simple preg_replace:
$replaced = preg_replace('~<p[^>]*><img src="([^"]+)"></p>~', '$1', $yourstring);
Explanation
<p matches the beginning of the tag
[^>]* matches any chars that are not a >
><img src=" matches literal characters
The parentheses in ([^"]+) capture any chars that are not a " to Group 1 (this is what you want)
"></p> matches chars to Group 1
We replace the whole string with $1, which is a backreference to the content captured by Group 1

Categories