How to remove 2 last characters with preg_replace? - php

I have a code like : 784XX . XX could be a character or number and I need an expression to remove the last 2 characters (XX) using ( and only ) preg_replace.
How can I do that?
For example, the output of :
782A3 is 782,
0012122 is 00121,
76542A is 7654,
333333CD is 333333,

You can use substr function.
But if you will use preg_replace you can do this:
$val = preg_replace('/[\w\d]{2}$/', '', $val);

I'm pretty sure there are much easier ways to do this task, yet if we wish to use regular expressions, we would be starting with just a simple expression such as:
(.+)?(..)
if I understand the problem right, and our desired output is in this capturing group:
(.+)
Demo
$re = '/(.+)?(..)/m';
$str = '782A3
0012122
76542A
333333CD';
$subst = '$1';
$result = preg_replace($re, $subst, $str);
echo $result;
RegEx Circuit
jex.im visualizes regular expressions:
Advice
AbraCadaver's advice in the comment is much better way:
substr('784XX', 0, -2);

Related

How to convert partially invalid JSON to a valid one?

I am using php to scrape a webpage and get this string:
'[{endTime:"2019-06-05T17:15:00.000+10:00",startTime:"2019-06-05T17:00:00.000+10:00"}]'
which is not valid json, the key names are encapsulated ...
I use preg_replace to create valid json:
$x = '[{endTime:"2019-06-05T17:15:00.000+10:00",startTime:"2019-06-05T17:00:00.000+10:00"}]'
$j = preg_replace('/(\w+)\s{0,1}:/', '"\1":', $x);
and get this value:
'[{"endTime":"2019-06-"05T17":"15":00.000+"10":00","startTime":"2019-06-"05T17":"00":00.000+"10":00"}]'
but I want this value:
'[{"endTime":"2019-06-05T17:15:00.000+10:00","startTime":"2019-06-05T17:00:00.000+10:00"}]'
How do I solve this problem?
RegEx 1
Your original expression seems to be find, we would just slightly modify that to:
([{,])(\w+)(\s+)?:
and it might work, we are adding a left boundary:
([{,])
and a right boundary:
:
and our key attribute is in this capturing group:
(\w+)
RegEx 2
We can expand our first expression to:
([{,])(\s+)?(\w+)(\s+)?:
in case, we might be having spaces before the key attribute:
Demo
Test 1
$re = '/([{,])(\w+)(\s+)?:/m';
$x = '[{endTime:"2019-06-05T17:15:00.000+10:00",startTime:"2019-06-05T17:00:00.000+10:00"}]';
$subst = '$1"$2":';
$result = preg_replace($re, $subst, $x);
echo $result;
Test 2
$re = '/([{,])(\s+)?(\w+)(\s+)?:/m';
$x = '[{endTime:"2019-06-05T17:15:00.000+10:00",startTime:"2019-06-05T17:00:00.000+10:00"}]';
$subst = '$1"$3":';
$result = preg_replace($re, $subst, $x);
echo $result;
Output
[{"endTime":"2019-06-05T17:15:00.000+10:00","startTime":"2019-06-05T17:00:00.000+10:00"}]
Demo
RegEx Circuit
jex.im visualizes regular expressions:
use this pattern :
([{,])([^:]+):
it will find all texts which are following by { or ,
and use this for replacement:
$1"$2":
It will add a doublequote on both sides of your word.

PHP exploding url from text, possible?

i need to explode youtube url from this line:
[embed]https://www.youtube.com/watch?v=L3HQMbQAWRc[/embed]
It is possible? I need to delete [embed] & [/embed].
preg_match is what you need.
<?php
$str = "[embed]https://www.youtube.com/watch?v=L3HQMbQAWRc[/embed]";
preg_match("/\[embed\](.*)\[\/embed\]/", $str, $matches);
echo $matches[1]; //https://www.youtube.com/watch?v=L3HQMbQAWRc
$string = '[embed]https://www.youtube.com/watch?v=L3HQMbQAWRc[/embed]';
$string = str_replace(['[embed]', '[/embed]'], '', $string);
See str_replace
why not use str_replace? :) Quick & Easy
http://php.net/manual/de/function.str-replace.php
Just for good measure, you can also use positive lookbehind's and lookahead's in your regular expressions:
(?<=\[embed\])(.*)(?=\[\/embed\])
You'd use it like this:
$string = "[embed]https://www.youtube.com/watch?v=L3HQMbQAWRc[/embed]";
$pattern = '/(?<=\[embed\])(.*)(?=\[\/embed\])/';
preg_match($pattern, $string, $matches);
echo $match[1];
Here is an explanation of the regex:
(?<=\[embed\]) is a Positive Lookbehind - matches something that follows something else.
(.*) is a Capturing Group - . matches any character (except a newline) with the Quantifier: * which provides matches between zero and unlimited times, as many times as possible. This is what is matched between the groups prior to and after. This are the droids you're looking for.
(?=\[\/embed\]) is a Positive Lookahead - matches things that come before it.

Regex replace recursive with one pattern

$array[key][key]...[key]
replace to
$array['key']['key']...['key']
I managed only to add quotes to the first keyword of the array.
\$([a-zA-Z0-9]+)\[([a-zA-Z_-]+[0-9]*)\] replace to \$\1\[\'\2\3\'\]
You may use a regex that does not perform a recursive, but consecutive matching:
$re = '/(\$\w+|(?!^)\G)\[([^]]*)\]/';
$str = "\$array[key][key][key]";
$subst = "$1['$2']";
$result = preg_replace($re, $subst, $str);
echo $result;
See IDEONE demo
The regex (\$\w+|(?!^)\G)\[([^]]*)\] matches all square parenthetical substrings (capturing their contents into Group 2) (with \[([^]]*)\]) that either are right after a '$'+alphanumerics substring (due to the \$\w+ part) or that follow one another consecutively (thanks to (?!^)\G).
Shouldn't need anything fancy, just get the stuff you need then
replace in a callback.
Untested:
$new_input = preg_replace_callback('/(?i)\$[a-z]+\K(?:\[[^\[\]]*\])+/',
function( $matches ){
return preg_replace( '/(\[)|(\])/', "$1'$2", $matches[0]);
},
$input );

Regular expressions replace

I need to remove
[0037][user name]
combination from a sentence. In the first brackets always containing numbers
eg:
[0032]
Digit count will not exceed than 4 by any chance. In the second brackets always containing letters eg:
[first name]
anyone have an idea how to do this?
You can use preg_replace() to implement regular expression syntax and try the following expression.
$str = preg_replace('/\[\d+]\[[a-z ]+]/i', '', $str);
\[\d{1,4}\]\[[a-zA-Z ]+\]
This should do it.Replace by empty string.See demo.
http://regex101.com/r/oE6jJ1/22
$re = "/\\[\\d{1,4}\\]\\[[a-zA-Z ]+\\]/im";
$str = "asdas asdsad [1234][asd asd] asdasd";
$subst = "";
$result = preg_replace($re, $subst, $str);

Get the number of matched characters in a regex group

I may be pushing the boundaries of Regular Expressions, but who knows...
I'm working in php.
In something like:
preg_replace('/(?:\n|^)(={3,6})([^=]+)(\1)/','<h#>$2</h#>', $input);
Is there a way to figure out how many '=' (={3,6}) matched, so I can backreference it where the '#'s are?
Effectively turning:
===Heading 3=== into <h3>Heading 3</h3>
====Heading 4==== into <h4>Heading 4</h4>
...
You can use:
preg_replace('/(?:\n|^)(={3,6})([^=]+)(\1)/e',
"'<h'.strlen('$1').'>'.'$2'.'</h'.strlen('$1').'>'", $input);
Ideone Link
No, PCRE can't do that. You should instead use preg_replace_callback and do some character counting then:
preg_replace_callback('/(?:\n|^)(={3,6})([^=]+)(\1)/', 'cb_headline', $input);
function cb_headline($m) {
list(, $markup, $text) = $m;
$n = strlen($markup);
return "<h$n>$text</h$n>";
}
Additionally you might want to be forgiving with the trailing === signs. Don't use a backreference but allow a variable number.
You might also wish to use the /m flag for your regex, so you can keep ^ in place of the more complex (?:\n|^) assertion.
It is very simple with modifier e in regexp, no need in preg_replace_callback
$str = '===Heading 3===';
echo preg_replace('/(?:\n|^)(={3,6})([^=]+)(\1)/e',
'implode("", array("<h", strlen("$1"), ">$2</h", strlen("$1"), ">"));',
$str);
or this way
echo preg_replace('/(?:\n|^)(={3,6})([^=]+)(\1)/e',
'"<h".strlen("$1").">$2</h".strlen("$1").">"',
$str);
I would do it like this:
<?php
$input = '===Heading 3===';
$h_tag = preg_replace_callback('#(?:\n|^)(={3,6})([^=]+)(\1)#', 'paragraph_replace', $input);
var_dump($h_tag);
function paragraph_replace($matches) {
$length = strlen($matches[1]);
return "<h{$length}>". $matches[2] . "</h{$length}>";
}
?>
Output:
string(18) "<h3>Heading 3</h3>"

Categories