I'm looking for a way to explode a string. For example, I have the following string: (we don't count the beginning - 0x)
0xa9059xbb000000000000000000000000fc7a5f48a1a1b3f48e7dcb1f23a1ea24199af4d00000000000000000000000000000000000000000000000000000000000054368
which is actually an ETH transaction input. I need to explode this string into 3 parts. Imagine 1 bunch of zeros is actually a single space and these spaces define the gates where the string should be exploded.
How can I do that?
preg_split()
This function uses a regular expression to split a string.
So in this example at two or more 0 in a row:
$arr = preg_split('/[0]{2,}/', $string);
print_r($arr);
echo PHP_EOL;
This will output the following:
Array
(
[0] => a9059xbb
[1] => fc7a5f48a1a1b3f48e7dcb1f23a1ea24199af4d
[2] => 54368
)
Be aware that you will have problems if a message itself has a 00 in it. Assuming it is used as a null-byte for "end of string", this will not happen, though.
preg_match()
This is an example using regular expressions. You can split at arbitrary points.
$string = 'a9059xbb000000000000000000000000fc7a5f48a1a1b3f48e7dcb1f23a1ea24199af4d00000000000000000000000000000000000000000000000000000000000054368';
print_r($string);
echo PHP_EOL;
$res = preg_match('/(.{4})(.{32})(.{32})/', $string, $matches);
print_r($matches);
echo PHP_EOL;
This outputs:
a9059xbb000000000000000000000000fc7a5f48a1a1b3f48e7dcb1f23a1ea24199af4d00000000000000000000000000000000000000000000000000000000000054368
Array
(
[0] => a9059xbb000000000000000000000000fc7a5f48a1a1b3f48e7dcb1f23a1ea24199a
[1] => a905
[2] => 9xbb000000000000000000000000fc7a
[3] => 5f48a1a1b3f48e7dcb1f23a1ea24199a
)
As you can see /(.{4})(.{32})(.{32})/ will find 4 bytes, then 32 and after that 32 again. Capturing groups are made with () around what you want to find. They appear in the $matches array (0 is always the whole string found).
In case you want to ignore certain parts you can express that as well:
/(.{4})9x(.{32}).{4}(.{32})/
This changes the found string:
Array
(
[0] => a9059xbb000000000000000000000000fc7a5f48a1a1b3f48e7dcb1f23a1ea24199af4d000
[1] => a905
[2] => bb000000000000000000000000fc7a5f
[3] => a1b3f48e7dcb1f23a1ea24199af4d000
)
Links
PHP documentation for the mentioned functions:
https://www.php.net/manual/en/function.preg-split.php
https://www.php.net/manual/en/book.pcre.php
Play around with the second regular expression using this demo:
https://regex101.com/r/pfZtH8/1
If you will always explode them at the same points (4 bytes(8 hexadecimal digits), 32 bytes(64 hexadecimal digits), 32 bytes(64 hexadecimal digits)), you could use substr().
$input = "0xa9059xbb000000000000000000000000fc7a5f48a1a1b3f48e7dcb1f23a1ea24199af4d00000000000000000000000000000000000000000000000000000000000054368";
$first = substr($input,2,8);
$second = substr($input,10,64);
$third = substr($input,74,64);
print_r($first);
print "<br>";
print_r($second);
print "<br>";
print_r($third);
print "<br>";
this outputs:
a9059xbb
000000000000000000000000fc7a5f48a1a1b3f48e7dcb1f23a1ea24199af4d0
0000000000000000000000000000000000000000000000000000000000054368
Related
I'm writing a PHP function to extract numeric ids from a string like:
$test = '123_123_Foo'
At first I took two different approaches, one with preg_match_all():
$test2 = '123_1256_Foo';
preg_match_all('/[0-9]{1,}/', $test2, $matches);
print_r($matches[0]); // Result: 'Array ( [0] => 123 [1] => 1256 )'
and other with preg_replace() and explode():
$test = preg_replace('/[^0-9_]/', '', $test);
$output = array_filter(explode('_', $test));
print_r($output); // Results: 'Array ( [0] => 123 [1] => 1256 )'
Any of them works well as long as the string does not content mixed letters and numbers like:
$test2 = '123_123_234_Foo2'
The evident result is Array ( [0] => 123 [1] => 1256 [2] => 2 )
So I wrote another regex to get rid off of mixed strings:
$test2 = preg_replace('/([a-zA-Z]{1,}[0-9]{1,}[a-zA-Z]{1,})|([0-9]{1,}[a-zA-Z]{1,}[0-9]{1,})|([a-zA-Z]{1,}[0-9]{1,})|([0-9]{1,}[a-zA-Z]{1,})|[^0-9_]/', '', $test2);
$output = array_filter(explode('_', $test2));
print_r($output); // Results: 'Array ( [0] => 123 [1] => 1256 )'
The problem is evident too, more complicated paterns like Foo2foo12foo1 would pass the filter. And here's where I got a bit stuck.
Recap:
Extract a variable ammount of chunks of numbers from string.
The string contains at least 1 number, and may contain other numbers
and letters separated by underscores.
Only numbers not preceded or followed by letters must be extracted.
Only the numbers in the first half of the string matter.
Since only the first half is needed I decided to split in the first occurrence of letter or mixed number-letter with preg_split():
$test2 = '123_123_234_1Foo2'
$output = preg_split('/([0-9]{1,}[a-zA-Z]{1,})|[^0-9_]/', $test, 2);
preg_match_all('/[0-9]{1,}/', $output[0], $matches);
print_r($matches[0]); // Results: 'Array ( [0] => 123 [1] => 123 [2] => 234 )'
The point of my question is if is there a simpler, safer or more efficient way to achieve this result.
If I understand your question correctly, you want to split an underscore-delimited string, and filter out any substrings that are not numeric. If so, this can be achieved without regex, with explode(), array_filter() and ctype_digit(); e.g:
<?php
$str = '123_123_234_1Foo2';
$digits = array_filter(explode('_', $str), function ($substr) {
return ctype_digit($substr);
});
print_r($digits);
This yields:
Array
(
[0] => 123
[1] => 123
[2] => 234
)
Note that ctype_digit():
Checks if all of the characters in the provided string are numerical.
So $digits is still an array of strings, albeit numeric.
Hope this helps :)
Getting just the numeric part of the string after the explode
$test2 = "123_123_234_1Foo2";
$digits = array_filter(explode('_', $test2 ), 'is_numeric');
var_dump($digits);
Result
array(3) { [0]=> string(3) "123" [1]=> string(3) "123" [2]=> string(3) "234" }
Use strtok
Regex isn't a magic bullet, and there are FAR simpler fixes for your problem, especially considering you're trying to split on a delimiter.
Any of the following approaches would be cleaner, and more maintainable, and the strtok() approach would probably perform better:
Use explode to create and loop through an array, checking each value.
Use preg_split to do the same, but with more a adaptable approach.
Use strtok, as it is designed exactly for this use-case.
Basic exmple for your case:
function strGetInts(string $str, str $delim) {
$word = strtok($str, $delim);
while (false !== $word) {
if (is_integer($word) {
yield (int) $word;
}
$word = strtok($delim);
}
}
$test2 = '123_1256_Foo';
foreach(strGetInts($test2, '_-') as $key {
print_r($key);
}
Note: the second argument to strtok is string containing ANY delimiter to split the string on. Thus, my example will group results into strings separated by underscores or dashes.
Additional Note: If and only if the string only needs to be split on a single delimiter (underscore only), a method using explode will likely result in better performance. For such a solution, see the other answer in this thread: https://stackoverflow.com/a/46937452/1589379 .
After instructing clients to input only
number comma number comma number
(no set length, but generally < 10), the results of their input have been, erm, unpredictable.
Given the following example input:
3,6 ,bannana,5,,*,
How could I most simply, and reliably end up with:
3,6,5
So far I am trying a combination:
$test= trim($test,","); //Remove any leading or trailing commas
$test= preg_replace('/\s+/', '', $test);; //Remove any whitespace
$test= preg_replace("/[^0-9]/", ",", $test); //Replace any non-number with a comma
But before I keep throwing things at it...is there an elegant way, probably from a regex boffin!
In a purely abstract sense this is what I'd do:
$test = array_filter(array_map('trim',explode(",",$test)),'is_numeric')
Example:
http://sandbox.onlinephpfunctions.com/code/753f4a833e8ff07cd9c7bd780708f7aafd20d01d
<?php
$str = '3,6 ,bannana,5,,*,';
$str = explode(',', $str);
$newArray = array_map(function($val){
return is_numeric(trim($val)) ? trim($val) : '';
}, $str);
print_r(array_filter($newArray)); // <-- this will give you array
echo implode(',',array_filter($newArray)); // <--- this give you string
?>
Here's an example using regex,
$string = '3,6 ,bannana,5,-6,*,';
preg_match_all('#(-?[0-9]+)#',$string,$matches);
print_r($matches);
will output
Array
(
[0] => Array
(
[0] => 3
[1] => 6
[2] => 5
[3] => -6
)
[1] => Array
(
[0] => 3
[1] => 6
[2] => 5
[3] => -6
)
)
Use $matches[0] and you should be on your way.
If you don't need negative numbers just remove the first bit in the in the regex rule.
If I have a string like this ,
$my_string="array('red','blue')";
How can I convert this to a real array ?
Example. :
$my_array=array('red','blue');
DO NOT USE EVAL. That is terrible overkill and very probably extremely unsafe.
While this is not the BEST way of doing this (as mentioned in question comments), you can use this below function to do exactly what you need.
How it works:
It uses Regex to find and split the string based on these layouts, the array is split using preg_split which is a regex verson of the more popular explode.
Once split the array will have some blank values so simply use array_filter to remove these blank values.
so:
// Explode string based on regex detection of:
//
// (^\h*[a-z]*\h*\(\h*')
// 1) a-z text with spaces around it and then an opening bracket
// ^ denotes the start of the string
// | denotes a regex OR operator.
// \h denotes whitespace, * denotes zero or more times.
//
// ('\h*,\h*')
// 2) or on '),(' with possible spaces around it
//
// ('\h*\)\h*$)
// 3) or on the final trailing '), again with possible spaces.
// $ denotes the end of the string
// the /i denotes case insensitive.
function makeArray($string){
$stringParts = preg_split("/(^\h*[a-z]*\h*\(\h*')|('\h*,\h*')|('\h*\)\h*$)/i",$string);
// now remove empty array values.
$stringParts = array_filter($stringParts);
return $stringParts;
}
Usage:
//input
$myString = " array('red','blue')";
//action
$array = makeArray($myString);
//output
print_r($array);
Output:
Array (
[1] => red
[2] => blue
)
Example 2:
$myString = " array('red','blue','horses', 'crabs (apples)', '(trapdoor)', '<strong>works</strong>', '436')";
$array = makeArray($myString);
print_r($array);
Output:
Array (
[1] => red
[2] => blue
[3] => horses
[4] => crabs (apples)
[5] => (trapdoor)
[6] => <strong>works</strong>
[7] => 436
)
Obviously the regex may need slight tweaking based on your exact circumstances but this is a very good starting point...
Reference Question/Answers
This question already has answers here:
php explode all characters [duplicate]
(4 answers)
Closed 8 years ago.
how i can explode string into an array. Acctually i want to translate english language into the braille. First thing i need to do is to get the character one by one from a string,then convert them by mathing the char from value in database and display the braille code using the pic. As example when user enter "abc ef", this will create value separately between each other.
Array
(
[0] => a
[1] => b
[2] => c
[3] =>
[4] => e
[5] => f
)
i tried to do but not get the desired output. This code separated entire string.
$papar = preg_split('/[\s]+/', $data);
print_r($papar);
I'm sorry for simple question,and if you all have an idea how i should do to translate it, feel free to help. :)
If you're using PHP5, str_split will do precisely what you're seeking to accomplish. It splits each character in a string – including spaces – into an individual element, then returns an array of those elements:
$array = str_split("abc ef");
print_r($array);
Outputs the following:
Array
(
[0] => a
[1] => b
[2] => c
[3] =>
[4] => e
[5] => f
)
UPDATE:
The PHP4 solution is to use preg_split. Pass a double forward slash as the matching pattern to delimit the split character-by-character. Then, set the PREG_SPLIT_NO_EMPTY flag to ensure that no empty pieces will be returned at the start and end of the string:
$array = preg_split('//', "abc ef", -1, PREG_SPLIT_NO_EMPTY); // Returns same array as above
PHP has a very simple method of getting the character at a specific index.
To do this, utilize the substring method and pass in the index you are looking for.
How I would approach your problem is
Ensure the string you are converting has at least a size of one
Determine how long the string is
int strlen ( string $string )
Loop over each character and do some operation depending on that character
With a string "abcdef"
$rest = substr("abcdef", -1); // returns "f"
See the substr page for a full example and more information
http://us2.php.net/substr
You can iterate the string itself.
$data = 'something string';
for($ctr = 0; $ctr < strlen($data); $ctr++)
{
if($data{$ctr}):
$kk = mysql_query("select braille_teks from braille where id_huruf = '$data{$ctr}'");
$jj = mysql_fetch_array($kk);
$gambar = $jj['braille_teks'];
?>
<img src="images/<?php echo $gambar;?>">
<?php
else:
echo " ";
}
Right now i'm trying to get this:
Array
(
[0] => hello
[1] =>
[2] => goodbye
)
Where index 1 is the empty string.
$toBeSplit= 'hello,,goodbye';
$textSplitted = preg_split('/[,]+/', $toBeSplit, -1);
$textSplitted looks like this:
Array
(
[0] => hello
[1] => goodbye
)
I'm using PHP 5.3.2
[,]+ means one or more comma characters while as much as possible is matched. Use just /,/ and it works:
$textSplitted = preg_split('/,/', $toBeSplit, -1);
But you don’t even need regular expression:
$textSplitted = explode(',', $toBeSplit);
How about this:
$textSplitted = preg_split('/,/', $toBeSplit, -1);
Your split regex was grabbing all the commas, not just one.
Your pattern splits the text using a sequence of commas as separator (its syntax also isn't perfect, as you're using a character class for no reason), so two (or two hundred) commas count just as one.
Anyway, since your just using a literal character as separator, use explode():
$str = 'hello,,goodbye';
print_r(explode(',', $str));
output:
Array
(
[0] => hello
[1] =>
[2] => goodbye
)