i have a string
$sting=
' [
type="user"
name="ali"
key="#$WRE"
//problem
address="{
"type":"hellow"
}"
]';
and i extract data with key=value format
for (;;) {
if(!preg_match('~([A-Za-z0-9]+)\=\"([^\"]*)\"~m', $string,$match)){
break;
}
$string=str_replace($match[0], '', $string);
$dataArray[$match[1]]=$match[2];
}
echo "<br><pre>";
print_r($dataArray);
echo "<br></pre>";
but output is
<br><pre>Array
(
[type] = user
[name] = ali
[key] = #$WRE
[address] = {
)
<br></pre>
According to [address]
(im not good at english For this reason, there may be errors in the sentences)
please help me
You can use a regex like
'/(\w+)\s*=\s*"(.*?)"\s*(?=$|\w+\s*=)/ms'
See the regex demo
Pattern details:
The /s is a DOTALL modifier that makes the . match any symbol including a newline
The /m modifier makes $ match the end of the line
(\w+) - Group 1 capturing 1 or more alphanumeric or underscore characters
\s* - zero or more whitespaces
= - an equal sign
\s* - 0+ whitespaces
"(.*?)" - a double quote, zero or more any chars other than a newline as few as possible up to the first double quote and this quote as well (Group 2 is what is captured in between double quotes)
\s* - zero or more whitespaces
(?=$|\w+\s*=) -a positive lookahead requiring the end of string to appear right after the current position or one or more alphanumeric followed with zero or more whitespaces and an equal sign.
Related
I want to parse a string to get the value inside a square bracket tag:
[vc_column_text][/vc_column_text]
I am using preg_match_all() in PHP
$string = '[vc_row][vc_column][/vc_column][/vc_row][vc_row][vc_column width="1/2"][vc_column_text css=".vc_custom_1576642149231{margin-bottom: 0px !important;}"]This is the string I want to fetch[/vc_column_text][/vc_column][/vc_row]`;
I tried this:
preg_match_all("'[vc_column_text(.*?)](.*?)[/vc_column_text]'", $string, $matches);
But this only returns an array of 2-3 characters:
A help will be very much appreciated :)
If you want to match only the sentence, you could use first match [vc_column_text followed by any char except [ or ] and then match the closing ]
Then match 0+ occurrences of a whitespace char and capture 1 or more occurrences of any char except a whitespace in group 1.
\[vc_column_text[^][]*\]\s*(.+?)\[/vc_column_text]
Explanation
\[vc_column_text Match [vc_column_text
[^][]*\] Match [, then 0+ occurrences of any char except [ or ] and match ]
\s* Match 0+ whitespace chars
(.+?) Capture group 1, match any char 1+ times non greedy
\[/vc_column_text] Match [/vc_column_text]
Regex demo | Php demo
Example code
$string = '[vc_row][vc_column][/vc_column][/vc_row][vc_row][vc_column width="1/2"][vc_column_text css=".vc_custom_1576642149231{margin-bottom: 0px !important;}"]This is the string I want to fetch[/vc_column_text][/vc_column][/vc_row]';
preg_match_all("~\[vc_column_text[^][]*\]\s*(.+?)\[/vc_column_text]~", $string, $matches);
print_r($matches[1]);
Output
Array
(
[0] => This is the string I want to fetch
)
I need regex to find all shortcode tag pairs that look like this [sc1-g-data]b[/sc1-g-data] but the number next to the sc can vary but they must match.
So something like this won't work \[sc(.*?)\-((.|\n)*?)\[\/sc(.*?)\- as this matches unmatching tag pairs like this which i don't want [sc1-g-data]b[/sc2-g-data]
so the expected number in the second tag depends on a random number in the first tag
You may use a regex like:
\[(sc\d*-[^\]\[]*)\]([\s\S]*?)\[\/\1\]
See the regex demo
\[ - a [ char
(sc\d*-[^\]\[]*) - Capturing group 1: sc, 0+ digits, -, and then 0+ chars other than ] and [
\] - a ] char
([\s\S]*?) - Capturing group 2: any 0+ chars, as few as possible
\[\/ - a [/ string
\1 - the same text stored in Group 1
\] - a ] char
See the regex graph:
PHP demo:
$pattern = '~\[(sc\d*-[^][]*)](.*?)\[/\1]~s';
$string = '[sc1-g-data]a[/sc1-g-data] ';
if (preg_match($pattern, $string, $matches)) {
print_r($matches);
}
Mind the use of a single quoted string literal, if you use a double quoted one you will need to use \\1, not \1 as '\1' != "\1" in PHP.
Output:
Array
(
[0] => [sc1-g-data]a[/sc1-g-data]
[1] => sc1-g-data
[2] => a
)
If your tags are just anything between brackets [blah][/blah] you can use:
\[(.*?)\].*?\[\/\1\]
I have a string:
access":"YOU HAVE 0 BALANCE","machine
How can I extract the string in between the double quotes and have only the text (without the double quotes):
YOU HAVE 0 BALANCE
I have tried
if(preg_match("'access":"(.*?)","machine'", $tok2, $matches)){
but with no luck :( .
You may use
'/access":"(.*?)","machine/'
See the regex demo. The value you need is in Group 1.
Details
access":" - a literal substring
(.*?) - Group 1: any 0+ chars other than line break chars, as few as possible, since *? is a lazy quantifier
","machine - a literal substring
See the PHP online demo:
$re = '/access":"(.*?)","machine/';
$str = 'access":"YOU HAVE 0 BALANCE","machine';
if (preg_match($re, $str, $matches)) {
print_r($matches[1]);
}
// => YOU HAVE 0 BALANCE
Let's say I want to split this string in two variables:
$string = "levis 501";
I will use
preg_match('/\d+/', $string, $num);
preg_match('/\D+/', $string, $text);
but then let's say I want to split this one in two
$string = "levis 5° 501";
as $text = "levis 5°"; and $num = "501";
So my guess is I should add a rule to the preg_match('/\d+/', $string, $num); that looks for numbers only at the END of the string and I want it to be between 2 and 3 digits.
But also the $text match now has one number inside...
How would you do it?
To slit a string in two parts, use any of the following:
preg_match('~^(.*?)\s*(\d+)\D*$~s', $s, $matches);
This regex matches:
^ - the start of the string
(.*?) - Group 1 capturing any one or more characters, as few as possible (as *? is a "lazy" quantifier) up to...
\s* - zero or more whitespace symbols
(\d+) - Group 2 capturing 1 or more digits
\D* - zero or more characters other than digit (it is the opposite shorthand character class to \d)
$ - end of string.
The ~s modifier is a DOTALL one forcing the . to match any character, even a newline, that it does not match without this modifier.
Or
preg_split('~\s*(?=\s*\d+\D*$)~', $s);
This \s*(?=\s*\d+\D*$) pattern:
\s* - zero or more whitespaces, but only if followed by...
(?=\s*\d+\D*$) - zero or more whitespaces followed with 1+ digits followed with 0+ characters other than digits followed with end of string.
The (?=...) construct is a positive lookahead that does not consume characters and just checks if the pattern inside matches and if yes, returns "true", and if not, no match occurs.
See IDEONE demo:
$s = "levis 5° 501";
preg_match('~^(.*?)\s*(\d+)\D*$~s', $s, $matches);
print_r($matches[1] . ": ". $matches[2]. PHP_EOL);
print_r(preg_split('~\s*(?=\s*\d+\D*$)~', $s, 2));
I am looking to find and replace words in a long string. I want to find words that start looks like this: $test$ and replace it with nothing.
I have tried a lot of things and can't figure out the regular expression. This is the last one I tried:
preg_replace("/\b\\$(.*)\\$\b/im", '', $text);
No matter what I do, I can't get it to replace words that begin and end with a dollar sign.
Use single quotes instead of double quotes and remove the double escape.
$text = preg_replace('/\$(.*?)\$/', '', $text);
Also a word boundary \b does not consume any characters, it asserts that on one side there is a word character, and on the other side there is not. You need to remove the word boundary for this to work and you have nothing containing word characters in your regular expression, so the i modifier is useless here and you have no anchors so remove the m (multi-line) modifier as well.
As well * is a greedy operator. Therefore, .* will match as much as it can and still allow the remainder of the regular expression to match. To be clear on this, it will replace the entire string:
$text = '$fooo$ bar $baz$ quz $foobar$';
var_dump(preg_replace('/\$(.*)\$/', '', $text));
# => string(0) ""
I recommend using a non-greedy operator *? here. Once you specify the question mark, you're stating (don't be greedy.. as soon as you find a ending $... stop, you're done.)
$text = '$fooo$ bar $baz$ quz $foobar$';
var_dump(preg_replace('/\$(.*?)\$/', '', $text));
# => string(10) " bar quz "
Edit
To fix your problem, you can use \S which matches any non-white space character.
$text = '$20.00 is the $total$';
var_dump(preg_replace('/\$\S+\$/', '', $text));
# string(14) "$20.00 is the "
There are three different positions that qualify as word boundaries \b:
Before the first character in the string, if the first character is a word character.
After the last character in the string, if the last character is a word character.
Between two characters in the string, where one is a word character and the other is not a word character.
$ is not a word character, so don't use \b or it won't work. Also, there is no need for the double escaping and no need for the im modifiers:
preg_replace('/\$(.*)\$/', '', $text);
I would use:
preg_replace('/\$[^$]+\$/', '', $text);
You can use preg_quote to help you out on 'quoting':
$t = preg_replace('/' . preg_quote('$', '/') . '.*?' . preg_quote('$', '/') . '/', '', $text);
echo $t;
From the docs:
This is useful if you have a run-time string that you need to match in some text and the string may contain special regex characters.
The special regular expression characters are: . \ + * ? [ ^ ] $ ( ) { } = ! < > | : -
Contrary to your use of word boundary markers (\b), you actually want the inverse effect (\B)-- you want to make sure that there ISN'T a word character next to the non-word character $.
You also don't need to use capturing parentheses because you are not using a backreference in your replacement string.
\S+ means one or more non-whitespace characters -- with greedy/possessive matching.
Code: (Demo)
$text = '$foo$ boo hi$$ mon$k$ey $how thi$ $baz$ bar $foobar$';
var_export(
preg_replace(
'/\B\$\S+\$\B/',
'',
$text
)
);
Output:
' boo hi$$ mon$k$ey $how thi$ bar '