substr gives empty results in PHP - php

I want to get the last 41 letters of a string, but every time its giving me a empty result.
The string is following:
02674bf7c88c9a025029f96d046651cfsingle100OK4917668157533262-07119519DEE0715DD708E6B65BC2412E1A8EE571F
Here is my code:
$urlstring = $_GET["o"];
$password = "bla";
$salt = "bla";
$result = decode($password, $urlstring, $salt);
if (strpos($result,'OK') !== false) {
$uservar = substr($result, -41);
$file = 'file.txt';
file_put_contents($file,$uservar);
}

Actually
$uservar = substr($result, -41);
does that, i.e. it will return last 41 chars. The problem most likely is that your decode function doesn't work and you never enter the if
$result = decode($password, $urlstring, $salt);
if (strpos($result,'OK') !== false) { // check if $result contains OK
$uservar = explode('-', $result);
$file = 'file.txt';
file_put_contents($file, $uservar[1]);
}

Change the folder permission to 777, and test the code again.

There are several ways to get the last part of the $result string provided in the question.
a) substr()
The function substr() is the most straightforward way to do it (as you already did).
$uservar = substr($result, -41);
b) regular expressions: preg_replace()
You can use preg_replace() to match the last 41 characters of the string into a group and replace the entire string with the group:
$uservar = preg_replace('/^.*(.{41})$/', '$1', $result);
The regular expression used for search:
^ is the beginning of the string;
.* is any character (.), zero or more times (*);
(.{41}) is any character (.), 41 times ({41}); the parentheses around the expression make a subpattern that can be used later in the regex or in the replacement string (as $1);
$ is the end of the string.
It matches any string that is at least 41 characters length; its last 41 characters are grouped in the first subpattern.
The replacement string ($1) refers to the 1st subpattern of the regex. It makes preg_replace() replace the matched string (the entire string) with its first subpattern (its last 41 characters). Read more about the PCRE patterns syntax.
c) convert the string to array of characters
Convert the string into an array of characters (str_split()), extract the correct slice of array (array_slice()), join the characters back (implode()).
$uservar = implode('', array_slice(str_split($result), -41));
This solution works the same as substr().
d) split the string into pieces using delimiter
If you are sure that the part of the string you need to extract does not contain any dash (-) and it starts right after the last dash then we don't even need to know its length. Use explode() to split $result into pieces delimited by dash (-) and the last piece is the part you need:
// Split the string into pieces
$pieces = explode('-', $result);
// Remove the last item from $pieces and return it
$uservar = array_pop($pieces);
// Alternatively, without modifying $pieces:
$uservar = end($pieces);
// Or
$uservar = $pieces[count($piece)-1];
e) ...
With little imagination, more complicated ways to extract a part of the string can be produced in a couple of lines of code.
Conclusion
Given $result is a not-empty string whose length is at least 41, all the above should work and produce the same result. The preg_replace() solution won't work for shorter strings (can be easily changed to work), the explode() solution doesn't care about 41 but uses - to separate the pieces.
If none of them works then your problem is somewhere else. Check for file rights, check if the code enters the if branch etc.

Related

Suggestion about search coincidences in string with PHP using REGEX

I am trying to search this coincidence in a string:
1. I need to take only numbers after the chracter '#' as long as this coincidence has not spaces, for example:
String = 'This is a test #VVC345RR, text, and more text 12345';
I want to take only this from my string -> 345.
My example:
$s = '\"access_token=103782364732640461|2. myemail#domain1.com ZmElnDTiZlkgXbT8e3 #DD234 4Jrw__.3600.1281891600-10000186237005';
$matches = array();
$s = preg_match('/#([0-9]+)/', $s, $matches);
print_r($matches);
This only works when I have one # and numbers.
Thanks!
Maybe:
#\D*\K(\d+)
Accomplishes what you want?
This will look for an #, any non-numbers, and then capture the numbers. The \K ignores the early match.
https://regex101.com/r/gNTccx/1/
I'm unclear what you mean by has not spaces, there are no spaces in the example string.

php Regex before a character and before another one

I have a list of :
firstname.lastname (location)
I'd like to extract the firstname, the lastname, and the location. It can be points in the location but it's always between parenthesis.
Can anyone help me please? (and give the explanation of the regex if possible, I dont know why I never can create my own regex...)
I found :
#\((.*?)\)# for the location
^[^\.]+ for the firstname
But I cant find for the lastname, and I dont know how to match all 3 together
You can do it without regex:
$string = 'firstname.lastname (location)';
//you get there array of name and surname
$exploded = explode('.',substr($string, 0, strpos($string, ' ')));
$name = $exploded[0];
$surname = $exploded[1];
//You get there location
$location = rtrim(explode(' (', $string)[1], ')');
You don't need regex for that. explode() on . with a limit of 2. Then strpos() first parenthesis ( and let substr() do the rest.
That's not too difficult with a regex. However, your confusion might stem from the fact that several of the characters in that example string are have special meanings in RegEx.
<?php
$string = "firstname.lastname (location)";
if(preg_match('/^(\w+)\.(\w+)\s*\((\w*)\)$/', $string, $aCapture)){
/*Let's break down that regex
^ Start of string
(\w+) Capture a string of continuous characters
\. a period
(\w+) Capture a string of continuous characters
\s Zero or more whitespace
\( An opening bracket
(\w+) Capture a string of continuous characters
\) An closing bracket
$ The end of the string
*/
$aCapture contains your captures; starting at position 1, because 0 will contain the entire string
$sFirstName = $aCapture[1];
$sLastName = $aCapture[2];
$sLocation = $aCapture[3];
print "$sFirstName, $sLastName, $sLocation";
}
?>
Using a formatted string:
$str = 'jacques.cheminade (espace)';
$result = sscanf($str, '%[^.].%[^ ] (%[^)])');
Note that if the syntax seems similar to the one used in regex, tokens [^...] don't use quantifiers as they describe parts of the string and not single characters.

Remove characters from both left and right of a string in PHP

This is an example of a string: abcde123#ijklmn0pq
In that string I need to print out only the numbers (the 123 sequence), and remove the letters (from both left and right) and the hashtag (#) to be removed as well.
The hashtag (#) is always included in the string.
The hashtag (#) is always positioned to the right of the characters that need to be printed;
The hashtag (#) is always positioned to the left of the characters that need to be removed;
Therefore, the hashtag (#) can be used as a guide to remove the letters from the Right
The number of characters in the beginning is always equal to 5 (constant) (to be removed);
The number of characters in the middle is always different (variable) (to be printed);
The number of characters in the right is always different (variable) (to be removed);
Here's another string example, similar to the first one: !!##$IMPORTANT#=-=whatever
The characters that need to be printed are the word "IMPORTANT"
As with the first example, what's on the left side of the hashtag (#) needs to be printed, but it's important to print only the "IMPORTANT" word, without the special characters "!!##$".
$myString = '!!##$IMPORTANT#=-=whatever';
$result = substr($myString, 5, -1);
$pos = strpos($result, '#');
$result = substr($result, 0, $pos);
echo $result;
You can use regexes with preg_replace();
Assuming that the string you need to process is stored in $string:
preg_replace('^.{5}(.*)#.*$', '$1', $string);
https://www.regex101.com/r/hA8lY7/1
First pattern explanation:
^.{5}: matches any 5 character after the start of $string
(.*): matches any N character after (1) before the first occurence of # (first capturing-group)
#.*$: matches # and any N character after (2) before the end of $string
Second pattern explanation:
$1: replaces $string with the first capturing-group matched in the first pattern
Ill give a stab at this. seems pretty simple.
function choppy($choppy) {
$nstr = substr($choppy, 5,strlen($choppy)); //chop first 5
$pos = strpos($nstr, "#"); //Find the position of the hash tag
return substr($nstr, 0, $pos); //we only need the stuff before it...
}
echo choppy('!!##$IMPORTANT#=-=whatever');
echo "\n";
echo choppy('abcde123#ijklmn0pq');
Result
C:\Users\developer\Desktop>php test.php
IMPORTANT
123
The other answers are good but if you need a one-liner for your homework:
$str = '!!##$IMPORTANT#=-=whatever';
echo substr($str, 5, strpos($str, '#')-5); //IMPORTANT

preg_split String into Array at First Non-Numeric Character

I have a string with some numbers and text and I'm trying to split the string at the first non-numeric character.
For Example, I have a few strings like
$value = '150px';
$value = '50em';
$value = '25%';
I've been trying to split the string using preg_split and a little regex.
$value_split = preg_split( '/[a-zA-Z]/' , $fd['yks-mc-form-padding'] );
I'm able to get the first part of the string using $value_split[0], for example I can store 150, or 50 or 25. I need to return the second part of the string as well (px, em or %).
How can I split the string using preg_split or something similar to return both parts of the array??
Thanks!
If you want to use regex and you haven't already, you should play with RegExr.
To do what you're wanting with regex, assuming all the strings will be all numeric together, followed by all non-numeric, you could do:
$matches = array();
preg_match('/([0-9]+)([^0-9]+)/',$value,$matches);
Then $matches[1] will be the numeric part and $matches[2] will be the rest
To break it down,
[0-9] matches any numeric character, so [0-9]+ matches 1 or more numeric characters in a row, so per the docs $matches[1] will have the (numeric) text matched in by the first set of parentheses
and [^0-9] matches any non-numeric character, so [^0-9]+ matches 1 or more non-numeric characters in a row and fills $matches[2] because it's in the 2nd set of parentheses
By preg_split() you cannot achieve what are you trying to. It will delete the part of your string which separates the whole string (in this case it will be separated by character [a-zA-Z]). Use preg_match() (or preg_match_all()) function.
You can use this pattern:
/([0-9]+)([a-zA-Z%]+)/
See demo.
Use the PREG_SPLIT_OFFSET_CAPTURE flag - it will cause an array to be returned, with item [0] being the string matched, and item [1] its starting position in the original string.
You can then use that info to extract the rest of the string by using ordinary sub-string functionality.
Something along the lines of:
$values_split = preg_split( '/[a-zA-Z]/' , $fd['yks-mc-form-padding'] );
$position = $values_split[0][1]
$length = $values_split[0][0]
$startPos = $position + $length
$numToGet = lenght($input) - $startPos
$remainder = substr($inline, startPos, $numToGet)

Identifying a random repeating pattern in a structured text string

I have a string that has the following structure:
ABC_ABC_PQR_XYZ
Where PQR has the structure:
ABC+JKL
and
ABC itself is a string that can contain alphanumeric characters and a few other characters like "_", "-", "+", "." and follows no set structure:
eg.qWe_rtY-asdf or pkl123
so, in effect, the string can look like this:
qWe_rtY-asdf_qWe_rtY-asdf_qWe_rtY-asdf+JKL_XYZ
My goal is to find out what string constitutes ABC.
I was initially just using
$arrString = explode("_",$string);
to return $arrString[0] before I was made aware that ABC ($arrString[0]) itself can contain underscores, thus rendering it incorrect.
My next attempt was exlpoding it on "_" anyway and then comparing each of the exploded string parts with the first string part until I get a semblance of a pattern:
function getPatternABC($string)
{
$count = 0;
$pattern ="";
$arrString = explode("_", $string);
foreach($arrString as $expString)
{
if(strcmp($expString,$arrString[0])!==0 || $count==0)
{
$pattern = $pattern ."_". $arrString[$count];
$count++;
}
else break;
}
return substr($pattern,1);
}
This works great - but I wanted to know if there was a more elegant way of doing this using regular expressions?
Here is the regex solution:
'^([a-zA-Z0-9_+-]+)_\1_\1\+'
What this does is match (starting from the beginning of the string) the longest possible sequence consisting of the characters inside the square brackets (edit that per your spec). The sequence must appear exactly twice, each time followed by an underscore, and then must appear once more followed by a plus sign (this is actually the first half of PQR with the delimiter before JKL). The rest of the input is ignored.
You will find ABC captured as capture group 1.
So:
$input = 'qWe_rtY-asdf_qWe_rtY-asdf_qWe_rtY-asdf+JKL_XYZ';
$result = preg_match('/^([a-zA-Z0-9_+-]+)_\1_\1\+/', $input, $matches);
if ($result) {
echo $matches[2];
}
See it in action.
Sure, just make a regular expression that matches your pattern. In this case, something like this:
preg_match('/^([a-zA-Z0-9_+.-]+)_\1_\1\+JKL_XYZ$/', $string, $match);
Your ABC is in $match[1].
If the presence of underscores in these strings has a low frequency, it may be worth checking to see if a simple explode() will do it before bothering with regex.
<?php
$str = 'ABC_ABC_PQR_XYZ';
if(substr_count($str, '_') == 3)
$abc = reset(explode('_', $str));
else
$abc = regexy_function($str);
?>

Categories