Error trying to pass regex match to function - php

I'm getting Syntax error, unexpected T_LNUMBER, expecting T_VARIABLE or '$'
This is the code i'm using
function wpse44503_filter_content( $content ) {
$regex = '#src=("|\')'.
'(/images/(19|20)(0-9){2}/(0|1)(0-9)/[^.]+\.(jpg|png|gif|bmp|jpeg))'.
'("|\')#';
$replace = 'src="'.get_site_url( $2 ).'"';
$output = preg_replace( $regex, $replace, $content );
return $output;
}
This is the line where i'm getting that error $replace = 'src="'.get_site_url( $2 ).'"';
Can anyone help me to fix it?
Thanks

You can't have '$2' as a variable name. It must start with a letter or underscore.
http://php.net/manual/en/language.variables.basics.php
Variable names follow the same rules as other labels in PHP. A valid variable name starts with a letter or underscore, followed by any number of letters, numbers, or underscores. As a regular expression, it would be expressed thus: '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'
Edit Above was my original answer and is the correct answer to the simple "syntax error" question. More in-depth answer below...
You are trying to use $2 to represent "the second capture group", but you haven't done anything at that point to match your regex. Even if $2 was a valid PHP variable name, it still wouldn't be set at that point in your script. Because of this, you can determine that you are using preg_replace improperly and that it may not suit your actual needs.
Note that the preg_replace documentation doesn't support using $n as a separate variable outside of the replacement operation. In other words, 'foo' . $1 . 'bar' is not a valid replacement string, but 'foo$1bar' is.
Depending on the complexity of get_site_url, you have 2 options:
If get_site_url is simply adding a root directory or server name, you could change your replacement string to src="/myotherlocation$2". This will effectively replace "/image/..." with "/myotherlocation/image/..." in the img src. This will not work if get_site_url is doing something more complex.
If get_site_url is complex, you should use preg_replace_callback per other answers. Give the documentation a read and post a new question (or I guess update this question?) if you have trouble with the implementation.

What you're trying to do (ie replacing the matched string with the result of a function call) can't be done using preg_replace, you'll need to use preg_replace_callback instead to get a function called for every match.
A short example of preg_replace_callback;
$get_site_url = // Returns replacement
function($row) {
return '!'.$row[1].'!'; // row[1] is first "backref"
};
$str = 'olle';
$regex = '/(ll)/'; // String to match
$output = preg_replace_callback( // Match, calling get_site_url for replacement
$regex,
$get_site_url,
$str);
var_dump($output); // output "o!ll!e"

PHP variable names cant begin with a number.

$2 is not a valid PHP variable. If you meant the second group in the regex then you want to put \2 in a string. However, since you're passing it to a function then you'll need to use preg_replace_callback() instead and substitute appropriately in the callback.

if PHP variable begins with number use following:
when I was getting the following as the result set from thrid party API
Code Works
$stockInfo->original->data[0]->close_yesterday
Code Failed
$stockInfo->original->data[0]->52_week_low
Solution
$stockInfo->original->data[0]->{'52_week_high'}

Related

Using different names for subpatterns of the same number with preg_replace_callback

I'm having a hard time getting my head around what exactly is being numbered in my regex subpatterns. I'm being given the PHP warning:
PHP Warning: preg_replace_callback(): Compilation failed: different names for subpatterns of the same number are not allowed
When attempting the following:
$input = "A string that contains [link-ssec-34] and a [i]word[/i] here";
$matchLink = "\[link-ssec-(0?[1-9]|[1-9][0-9]|100)\]";
$matchItalic = "\[i](.+)\[\/i]";
$output = preg_replace_callback(
"/(?|(?<link>$matchLink)|(?<italic>$matchItalic))/",
function($m) {
if(isset($m['link'])){
$matchedLink = substr($m['link'][0], 1, -1);
//error_log('m is: ' . $matchedLink);
$linkIDExplode = explode("-",$matchedLink);
$linkHTML = createSubSectionLink($linkIDExplode[2]);
return $linkHTML;
} else if(isset($m['italic'])){
// TO DO
}
},
$input);
If I remove the named capture groups, like so:
"/(?|(?:$matchLink)|(?:$matchItalic))/"
There's no warnings, and I get matches fine but can't target them conditionally in my function. I believe I'm following correct procedure for naming capture groups, but PHP is saying they're using the same subpattern number, which is where I'm lost as I'm not sure what's being numbered. I'm familiar with addressing subpatterns using $1, $2, etc. but don't see the relevancy here when used with named groups.
Goal
Incase I'm using completely the wrong technique, I should include my goal. I was originally using preg_replace_callback() to replace tagged strings that matched a pattern like so :
$output = preg_replace_callback(
"/\[link-ssec-(0?[1-9]|[1-9][0-9]|100)\]/",
function($m) {
$matchedLink = substr($m[0], 1, -1);
$linkIDExplode = explode("-",$matchedLink);
$linkHTML = createSubSectionLink($linkIDExplode[2]);
return $linkHTML;
},
$input);
The requirement has grown to needing to match multiple tags in the same paragraph (My original example included the next one [i]word[/i]. Rather than parsing the entire string from scratch for each pattern, I'm trying to look for all the patterns in a single sweep of the paragraph/string in the belief that it will be less taxing on the system. Researching it led me to believe that using named capture groups in a branch reset was the best means of being able to target matches with conditional statements. Perhaps I'm walking down the wrong trail with this one but would appreciate being directed to a better method.
Result Desired
$input = "A string that contains [link-ssec-34] and a [i]word[/i] here";
$output = "A string that contains <a href='linkfromdb.php'>Link from Database</a> and a <span class='italic'>word</span> here."
With the potential to add further patterns as needed in the format of square brackets encompassing a word or being self-contained.
To answer your question about the warning:
PHP Warning: preg_replace_callback(): Compilation failed: different names for subpatterns of the same number are not allowed
Your pattern defines named matchgroups. But your pattern is using alternations (|) as well, meaning a whole part of the pattern does not need to be matched as all.
That means, that the named pattern link can appear with the match-number 1, but italic can also appear with match-number 1.
Since there is an alternation BOTH the matches can only be the same "number", hence they are only allowed to have the same NAME:
#(?|(?<first>one)|(?<first>two))#
would be allowed.
#(?|(?<first>one)|(?<second>two))#
throws this warning.
Without fully understand what I've done (but will look into it now) I did some trial and error on #bobblebubble comment and got the following to produce the desired result. I can now use conditional statements targeting named capture groups to decide what action to take with matches.
I changed the regex to the following:
$matchLink = "\[link-ssec-(0?[1-9]|[1-9][0-9]|100)\]"; // matches [link-ssec-N]
$matchItalic = "\[i](.+)\[\/i]"; // matches [i]word[/i]
$output = preg_replace_callback(
"/(?<link>$matchLink)|(?<italic>$matchItalic)/",
function($m) { etc...
Hopefully it's also an efficient way, in terms of overhead, of matching multiple regex patterns with callbacks in the same string.

How to get a number from a html source page?

I'm trying to retrieve the followed by count on my instagram page. I can't seem to get the Regex right and would very much appreciate some help.
Here's what I'm looking for:
y":{"count":
That's the beginning of the string, and I want the 4 numbers after that.
$string = preg_replace("{y"\"count":([0-9]+)\}","",$code);
Someone suggested this ^ but I can't get the formatting right...
You haven't posted your strings so it is a guess to what the regex should be... so I'll answer on why your codes fail.
preg_replace('"followed_by":{"count":\d')
This is very far from the correct preg_replace usage. You need to give it the replacement string and the string to search on. See http://php.net/manual/en/function.preg-replace.php
Your second usage:
$string = preg_replace(/^y":{"count[0-9]/","",$code);
Is closer but preg_replace is global so this is searching your whole file (or it would if not for the anchor) and will replace the found value with nothing. What your really want (I think) is to use preg_match.
$string = preg_match('/y":\{"count(\d{4})/"', $code, $match);
$counted = $match[1];
This presumes your regex was kind of correct already.
Per your update:
Demo: https://regex101.com/r/aR2iU2/1
$code = 'y":{"count:1234';
$string = preg_match('/y":\{"count:(\d{4})/', $code, $match);
$counted = $match[1];
echo $counted;
PHP Demo: https://eval.in/489436
I removed the ^ which requires the regex starts at the start of your string, escaped the { and made the\d be 4 characters long. The () is a capture group and stores whatever is found inside of it, in this case the 4 numbers.
Also if this isn't just for learning you should be prepared for this to stop working at some point as the service provider may change the format. The API is a safer route to go.
This regexp should capture value you're looking for in the first group:
\{"count":([0-9]+)\}
Use it with preg_match_all function to easily capture what you want into array (you're using preg_replace which isn't for retrieving data but for... well replacing it).
Your regexp isn't working because you didn't escaped curly brackets. And also you didn't put count quantifier (plus sign in my example) so it would only capture first digit anyway.

how to get the text enclosed by quotations using php

So I have a pretty large dump file that I have to extract specific content from it.
The file has record each containing specific numbers enclosed by ". Bellow is a sample part of the file:
Ali Rabi (CustomerId=["3453456"]) // need to get: 3453456
Mohammad Reza Saberi (CustomerId=["12328"]) // need to get: 12328
Currently I read line by line and get the IDs as bellow. the code works fine and I get the result I want:
$cid = substr($row, strpos($row, '[') +2, strpos($row, ']')-strpos($row, '[')-2);
echo $cid;
But doesn't PHP have a function for this? getting the string enclosed by some delimiters?
If all your records look like the ones you've mentioned, I think it's the perfect place where you could use regular expressions.
Regular Expressions help you to create and find patterns in a given String.
For your case, you could probably use :
if (preg_match("/[0-9]+/", "Ali Rabi (CustomerId=[\"3453456\"])", $matches)) {
echo "Match was found <br />";
echo $matches[0];
}
The preg_match() function helps you to find the matches. The first param for this function is the pattern you're looking for. In your case you're looking for a set of continuous digits each of which can range from 0-9.
So, for a single digit we use [0-9]. Adding a + after [0-9] means that there needs to be atleast one digit in the match. Hence, [0-9]+ as the regular expression.
Read more about regular expressions in php : http://webcheatsheet.com/php/regular_expressions.php
Try:
<?php preg_match_all("/([1-9]+)/",$yourtext, $result, PREG_PATTERN_ORDER); ?>
$result contains all Matches.
Further Infomartion: http://php.net/manual/de/function.preg-match-all.php
I think you can use str_replace to remove the "
$cid = str_replace('"','',$row);

Extract last instance of a regular expression from string in PHP

I have a URL that is in the following structure: http://somewebsite.com/directory1/directory2/directory3...
I'm trying to get the last directory name from this url, but the depth of the url isn't always constant so i don't think i can use a simple substr or preg_match call - is there a function to get the last instance of a regular expression match from a string?
Just use:
basename( $url )
It should have the desired effect
Torben's answer is the correct way to handle this specific case. But for posterity, here is how you get the last instance of a regular expression match:
preg_match_all('/pattern/', 'subject', $matches, PREG_SET_ORDER);
$last_match = end($matches); // or array_pop(), but it modifies the array
$last_match[0] contains the complete match, $last_match[1] contains the first parenthesized subpattern, etc.
Another point of interest: your regular expression '/\/([^/])$/' should work as-is because the $ anchors it to the end.

regex to find all text after delimited string

I have some content that contains a token string in the form
$string_text = '[widget_abc]This is some text. This is some text, etc...';
And I want to pull all the text after the first ']' character
So the returned value I'm looking for in this example is:
This is some text. This is some text, etc...
preg_match("/^.+?\](.+)$/is" , $string_text, $match);
echo trim($match[1]);
Edit
As per author's request - added explanation:
preg_match(param1, param2, param3) is a function that allows you to match a single case scenario of a regular expression that you're looking for
param1 = "/^.+?](.+?)$/is"
"//" is what you put on the outside of your regular expression in param1
the i at the end represents case insensitive (it doesn't care if your letters are 'a' or 'A')
s - allows your script to go over multiple lines
^ - start the check from the beginning of the string
$ - go all the way to end of the string
. - represents any character
.+ - at least one or more characters of anything
.+? - at least one more more characters of anything until you reach
.+?] - at least one or more characters of anything until you reach ] (there is a backslash before ] because it represents something in regular expressions - look it up)
(.+)$ - capture everything after ] and store it as a seperate element in the array defined in param3
param2 = the string that you created.
I tried to simplify the explanations, I might be off, but I think I'm right for the most part.
The regex (?<=]).* will solve this problem if you can guarantee that there are no other square brackets on the line. In PHP the code will be:
if (preg_match('/(?<=\]).*/', $input, $group)) {
$match = $group[0];
}
This will transform [widget_abc]This is some text. This is some text, etc... into This is some text. This is some text, etc.... It matches everything that follows the ].
$output = preg_replace('/^[^\]]*\]/', '', $string_text);
Is there any particular reason why a regex is wanted here?
echo substr(strstr($string_text, ']'), 1);
A regex is definitely overkill for this instance.
Here is a nice one-liner :
list(, $result) = explode(']', $inputText, 2);
It does the job and is way less expensive than using regular expressions.

Categories