I want to split a 4 digit number with 4 digit decimal .
Inputs:
Input 1 : 5546.263
Input 2 : 03739.712 /*(some time may have one zero at first)*/
Result: (array)
Result of input 1 : 0 => 55 , 1 => 46.263
Result of input 2 : 0 => 37 , 1 => 39.712
P.S : Inputs is GPS data and always have 4 digit as number / 3 digit as decimal and some time have zero at first .
You could use the following function:
function splitNum($num) {
$num = ltrim($num, '0');
$part1 = substr($num, 0, 2);
$part2 = substr($num, 2);
return array($part1, $part2);
}
Test case 1:
print_r( splitNum('5546.263') );
Output:
Array
(
[0] => 55
[1] => 46.263
)
Test case 2:
print_r( splitNum('03739.712') );
Output:
Array
(
[0] => 37
[1] => 39.712
)
Demo!
^0*([0-9]{2})([0-9\.]+) should work just fine and do what you want:
$input = '03739.712';
if (preg_match('/^0*([0-9]{2})([0-9\.]+)/', $input, $matches)) {
$result = array((int)$matches[1], (float)$matches[2]);
}
var_dump($result); //array(2) { [0]=> int(37) [1]=> float(39.712) }
Regex autopsy:
^ - the string MUST start here
0* - the character '0' repeated 0 or more times
([0-9]{2}) - a capturing group matching a digit between 0 and 9 repeated exactly 2 times
([0-9\.]+) - a capturing group matching a digit between 0 and 9 OR a period repeated 1 or more times
Optionally you can add $ to the end to specify that "the string MUST end here"
Note: Since we cast to an int in the first match, you can omit the 0* part, but if you plan NOT to cast it, then leave it in.
Related
i have a text and i want convert it to array by exclude but i cant get true array
# SRC-ADDRESS DST-ADDRESS PACKETS BYTES SRC-USER DST-USER 0 10.40.47.48 216.58.205.211 12 822 2 1 10.40.47.48 102.132.97.21 66 9390 2 2 184.106.10.77 10.40.47.252 10 1819 1 3 10.40.47.252 104.27.155.225 1 41 1 4 10.40.47.252 144.76.103.6 5 878 1 5 102.132.97.35 10.40.47.252 11 1159 1 6 10.40.47.252 52.169.53.217 1 397 1 7 104.27.155.225 10.40.47.252 1 52 1
and i want result like this
Array
(
[0] => Array
(
[.id] => *0
[src-address] => 10.40.47.50
[dst-address] => 185.144.157.141
[packets] => 6
[bytes] => 1349
)
[1] => Array
(
[.id] => *1
[src-address] => 195.122.177.151
[dst-address] => 10.40.47.48
[packets] => 4
[bytes] => 174
[dst-user] => 2
)
....
i try this but it is wrong
$arr = exclude(" ",$text);
edit :
i can get text by another way
0 src-address=108.177.15.188 dst-address=10.40.47.252 packets=1 bytes=52 dst-user="1" 1 src-address=10.40.47.48 dst-address=172.217.19.150 packets=11 bytes=789 src-user="2" 2 src-address=184.106.10.77 dst-address=10.40.47.252 packets=26 bytes=5450 dst-user="1"
As I mentioned in the comments, one way would be to first explode your input by " " (space). You loop through each element/row of the resulting array. Then you explode each of those by = (equals sign). If the result of that explode is a single-element array, you know you should start a new row and create a key-value pair using your special .id key. If the count of the result is two, take the first part and make it the key of a new key-value pair in the current row, and take the second part and make it the value of that key-value pair.
There's a bit of a wrinkle in the fact that some of your source values are quoted, but you seem to want them not quoted in the result. To handle that we do a lose equality check on the value to see if it is the same when converted to an integer or not. If it is, then we convert it to remove the quotes.
$inputText = '0 src-address=108.177.15.188 dst-address=10.40.47.252 packets=1 bytes=52 dst-user="1" 1 src-address=10.40.47.48 dst-address=172.217.19.150 packets=11 bytes=789 src-user="2" 2 src-address=184.106.10.77 dst-address=10.40.47.252 packets=26 bytes=5450 dst-user="1"';
$result = array();
$spaceParts = explode(" ", $inputText);
foreach($spaceParts as $part)
{
$subParts = explode("=", $part);
if(count($subParts) == 1)
{
$resultIndex = (isset($resultIndex) ? $resultIndex+1 : 0);
$result[$resultIndex] = array(".id" => "*".$part);
}
else if(count($subParts) == 2)
{
$result[$resultIndex][$subParts[0]] = ((int)$subParts[1] == $subParts[1] ? (int)$subParts[1] : $subParts[1]);
}
else
{
// unexpected, handle however you want
}
}
print_r($result);
DEMO
Try reading the string in using str_getcsv replacing the delimiter with whatever the string is delimited by.
var_dump(str_getcsv($input, ","));
Note the manual states that the delimiter must be one char long. If wanting a tab or multiple spaces you will need to look into the answer:
str_getcsv on a tab-separated file
str-getcsv php manual
Here is something that could work but I would recoment using the csv methods instead to read the data in . And it is unclear how your data should be actually mapped to header.
$header = "# SRC-ADDRESS DST-ADDRESS PACKETS BYTES SRC-USER DST-USER ";
$input = "# SRC-ADDRESS DST-ADDRESS PACKETS BYTES SRC-USER DST-USER 0 10.40.47.48 216.58.205.211 12 822 2 1 10.40.47.48 102.132.97.21 66 9390 2 2 184.106.10.77 10.40.47.252 10 1819 1 3 10.40.47.252 104.27.155.225 1 41 1 4 10.40.47.252 144.76.103.6 5 878 1 5 102.132.97.35 10.40.47.252 11 1159 1 6 10.40.47.252 52.169.53.217 1 397 1 7 104.27.155.225 10.40.47.252 1 52 1 ";
$string = str_replace($header, "", $input );
$delimiter = " ";
$columns = 6;
$splitData = explode($delimiter, $string);
$result = [];
$i= 0;
foreach ($splitData as $key => $value) {
$result[$i][] = $value;
if (($key+1) % $columns == 0 ){
$i++;
}
}
var_dump($result);
Using the second example with the 0 src-address=108.177.15.188 dst-address=10.40.47.252 packets=1 bytes=52 dst-user="1" format, there are 6 entries:
$result = array_map(function($v) {
parse_str("id=".implode("&", $v), $output);
return $output;
}, array_chunk(explode(' ', $text), 6));
Explode the array on spaces
Chunk the array into 6 entries per element
Map to a function that implodes each array on & and parse it as a query string
I have a personal expression:
GREATER (5.26; 7; LESSER (3.00; 6; GREATER (7; 8)))
I would like a regex a function that would return what contains the parentheses with delimiter for example passing "GREATER" as an expression the regex would return an array with
[0] => 5.26; 7
[1] => 7; 8
I'm using this regex preg_match_all("/\((([^()]*|(?R))*)\)/", $valor, $matches); but it does not return me correctly.
Does anyone have any light on this regex?
I would recommend the regex /(?<=GREATER\s\()([\d.]+)(?:;\s)([\d.]+)/g.
Breaking this down:
(?<=GREATER\s\() - Does a positive lookbehind on GREATER (
([\d.]+) - Grabs any digits and dots that follow this, and groups them
(?:;\s) - Processes but doesn't group the ; and space
([\d.]+) - Grabs any digits and dots that follow this, and groups them
The global flag (g) is required for this to target each of the sets.
Run against the string GREATER (5.26; 7; LESSER (3.00; 6; GREATER (7; 8)))
This gives:
array(3
0 => array(2
0 => 5.26; 7
1 => 7; 8
)
1 => array(2
0 => 5.26
1 => 7
)
2 => array(2
0 => 7
1 => 8
)
)
This allows you access to the 'combined' two sets that proceed the word GREATER in the first grouping, in addition to separating the sets out in the subsequent groupings (allowing for easy access).
This can be seen working at PHPLiveRegex here.
I want to get this results (from -> to)
# use string length limit = 3
1 {2 3} -> 1 # the string between the {} must be whole
1 2 3 -> 1 2
1 23 -> 1
{1} -> {1}
{1 2} -> empty
123456 -> 123 # if there is no spaces, cut string by symbols (except {*} expressions). Not necessarily but it would be cool
# one more example. Use string length limit = 5
{1} 2 -> {1} 2
123 45 -> 123
123 4 -> 123 4
Is there a way to do this using PHP with one regex expression?
Length limit may be dynamic.
Similar question - Get first 100 characters from string, respecting full words (but my question requires full contain {*} expressions )
I tried: ^(.{1,3})({.*}|\s|$)
The idea here is to define your atomic bits, match each, and use a negative lookbehind to limit the character length (also makes sure to ditch trailing whitespace as well - not sure if this is needed or not, but figured I'd throw it in.)
Only other thing is to use a conditional expression to see whether it's just a single uninterrupted series of chars and split it naively if so (for your 123456 -> 123 example.)
function truncate($string, $length)
{
$regex = <<<REGEX
/
(?(DEFINE)
(?<chars> [^\s{}]+ )
(?<group> { (?&atom)* } )
(?<atom> (?&chars) | (?&group) | \s )
)
\A
(?(?=.*[\s{}])
(?&atom)*(?<! \s | .{{$length}}. ) |
.{0,$length}
)
/x
REGEX;
preg_match($regex, $string, $matches);
return $matches[0];
}
$samples = <<<'DATA'
1 {2 3}
1 2 3
1 23
{1}
{1 2}
123456
DATA;
foreach (explode("\n", $samples) as $sample) {
var_dump(truncate($sample, 3));
}
Output:
string(1) "1"
string(3) "1 2"
string(1) "1"
string(3) "{1}"
string(0) ""
string(3) "123"
And:
$samples = <<<'DATA'
{1} 2
123 45
123 4
DATA;
foreach (explode("\n", $samples) as $sample) {
var_dump(truncate($sample, 5));
}
Outputs:
string(5) "{1} 2"
string(3) "123"
string(5) "123 4"
The solution using preg_match_all function with specific regex pattern:
$str = '1 {2 3}
1 2 3
1 23
{1}
{1 2}
123456 ';
$re = '/^(\S \S{1}(?=\s)|\S(?= \S{2})|\{\S\}|\w{3}(?=\w))/m';
preg_match_all($re, $str, $matches);
// the new line containing truncated items(you can `implode` it to get a single string)
print_r($matches[0]);
The output:
Array
(
[0] => 1
[1] => 1 2
[2] => 1
[3] => {1}
[4] => 123
)
Regex demo (check "Explanation" section at the right side)
try this one:
/^([\w ]{1,3}(?= )|\w{1,3}|\{\w\})/gm
It's working with given samples https://regex101.com/r/iF2tSp/3
1 {2 3}
1 2 3
1 23
{1}
{1 2}
123456
Match 1
Full match 0-1 `1`
Group 1. n/a `1`
Match 2
Full match 8-11 `1 2`
Group 1. n/a `1 2`
Match 3
Full match 14-15 `1`
Group 1. n/a `1`
Match 4
Full match 19-22 `{1}`
Group 1. n/a `{1}`
Match 5
Full match 29-32 `123`
Group 1. n/a `123`
Let's say I have random block of text:
EAMoAAQAABwEBAAAAAAAAAAAAAAABAgMFBgcIBAkBAQABBQEBAAAAAAAAAAAAAAAGAgMEBQcBCBAAAQMDAgMEBQcIBQgGCwEAAQACAxEEBSEGMRIHQVFhE3GBIhQIkaGxwTJCI9FScoKSojMV8GLCUxbhstKDo7M0ZHOTJEQlF/HiQ2PDVHSExEUmGBEBAAIBAgMDCAgCCgMBAQEAAAECAxEEITEFQRIGUWFxgZGhIhPwscHRMlIUB0Jy4fGCkqLCI1MVFrLSQ2IzF//aAAwDAQACEQMRAD8A7+QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEEDwXkzpxHgusxi7NrnXF3G0NBLhzAkAeAqVH934r6bt57uTPSJ8ne1n2Rqycezy35VlRttwYu5DXNlLOcczOdpHM3hUUqtLs/wBxulZonXJ8vjp8caa+eOa5k6flrPLVcIbm3n/gytf4NcCVKtj1XbbqNcOSuT+W0W+pi3x2rzjRWWxUCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAggV5It2Uy8GNYAWmW6kr5MDftO8T3BRXxR4s2/SccTb48lvw0jnPnn8tfP6o1Ze02ds08OERzlid+/P5Orp5BHEeFuxxa0Dxpx9a+fOu+Iup9Tmfm30p+Ss92vr/N6bat/t67fDyjWfLLG79pt45YpAA8NdUAg9ngolTFNbedtqWi0avVicv5bLKFr2kSRltHaahrXCnylZcd6k208rDy4ItxlkUr5+XnZE1zxq0h3KfUQqv1GWsxeI0tHKY1rPtjRgVivKZU7HebrS491ybX+TWnO7V7PEn7w+f0rpPhb9zdxt7Rj3szkx/n/AI6+n88f4vTyebno8Wr3qTGvun7mawSxzsbNC4Pje0Oa9pqCD2grv+3z0zUi9Ji1bRrEx2wjtqzWdJ5wqq8pEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQU
SPECIFICATIONS:
patternABC >= 2 characters = groupABC IF groupABC occurs more than once
groupABC + (groupABC)n = sequence WHERE n >= 1 AND sequence > 6 characters
** A sequence needs to be > 6 characters in order to be evaluated
BREAKDOWN:
How do I find any repeating patterns that occur in sequence?
QEBAQEBAQEBAQEBAQEBAQEBA
I also want to count how many times each group repeats:
QEBA QEBA QEBA QEBA QEBA QEBA = 6
Also the sequence must be > 6 characters in order to be evaluated:
NO GOOD: AA AA AA
GOOD: AA AA AA AA
It would be ideal if the output could be stored in an associative array, with duplicate entries removed:
QEBA => 6, AA => 4, QEBA => 3, AA => 8, (QEBA => 6)<- REMOVE
Does anyone have the time & the inclination to tackle this problem?
You rock if you do!
$str = 'EAMoAAQAABwEBAAAAAAAAAAAAAAABAgMFBgcIBAkBAQABBQEBAAAAAAAAAAAAAAAGAgMEBQcBCBAAAQMDAgMEBQcIBQgGCwEAAQACAxEEBSEGMRIHQVFhE3GBIhQIkaGxwTJCI9FScoKSojMV8GLCUxbhstKDo7M0ZHOTJEQlF/HiQ2PDVHSExEUmGBEBAAIBAgMDCAgCCgMBAQEAAAECAxEEITEFQRIGUWFxgZGhIhPwscHRMlIUB0Jy4fGCkqLCI1MVFrLSQ2IzF//aAAwDAQACEQMRAD8A7+QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEEDwXkzpxHgusxi7NrnXF3G0NBLhzAkAeAqVH934r6bt57uTPSJ8ne1n2Rqycezy35VlRttwYu5DXNlLOcczOdpHM3hUUqtLs/wBxulZonXJ8vjp8caa+eOa5k6flrPLVcIbm3n/gytf4NcCVKtj1XbbqNcOSuT+W0W+pi3x2rzjRWWxUCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAggV5It2Uy8GNYAWmW6kr5MDftO8T3BRXxR4s2/SccTb48lvw0jnPnn8tfP6o1Ze02ds08OERzlid+/P5Orp5BHEeFuxxa0Dxpx9a+fOu+Iup9Tmfm30p+Ss92vr/N6bat/t67fDyjWfLLG79pt45YpAA8NdUAg9ngolTFNbedtqWi0avVicv5bLKFr2kSRltHaahrXCnylZcd6k208rDy4ItxlkUr5+XnZE1zxq0h3KfUQqv1GWsxeI0tHKY1rPtjRgVivKZU7HebrS491ybX+TWnO7V7PEn7w+f0rpPhb9zdxt7Rj3szkx/n/AI6+n88f4vTyebno8Wr3qTGvun7mawSxzsbNC4Pje0Oa9pqCD2grv+3z0zUi9Ji1bRrEx2wjtqzWdJ5wqq8pEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQU';
preg_match_all( '/(\S{2,}?)\1+/', $str, $matches );
// Remove duplicates
$matches[0] = array_unique( $matches[0] );
foreach ( $matches[0] as $key => $value ) {
if ( strlen( $value ) > 6 ) {
$repeated = $matches[1][$key];
$results[] = array( $repeated => count( explode( $repeated, $value ) ) - 1 );
}
}
print_r($results);
/*
[AA] => 7
[QEBA] => 93
[CAgI] => 18
[EBAQ] => 18
*/
The above assumes a sequence is composed of non-space characters.
Get the sequences with preg_match_all('/(?:(.{6,})\1)/',$inputText,$sequences)
(note: sequences will be saved in $sequences)
Explained RegEx demo: http://regex101.com/r/rW4nE2
Use array_unique() to get rid of duplicates.
Loop through each sequence and:
Get the groups with preg_match_all('/(.+?)(\1)(\1)?/',$sequence,$groups)
Explained RegEx demo: http://regex101.com/r/pC3pB7
Use count() if you need to.
Is there a way using regex to replace characters in a string based on position?
For instance, one of my rewrite rules for a project I’m working on is “replace o with ö if o is the next-to-last vowel and even numbered (counting left to right).”
So, for example:
heabatoik would become heabatöik (o is the next-to-last vowel, as well as the fourth vowel)
habatoik would not change (o is the next-to-last vowel, but is the third vowel)
Is this possible using preg_replace in PHP?
Starting with the beginning of the subject string, you want to match 2n + 1 vowels followed by an o, but only if the o is followed by exactly one more vowel:
$str = preg_replace(
'/^((?:(?:[^aeiou]*[aeiou]){2})*)' . # 2n vowels, n >= 0
'([^aeiou]*[aeiou][^aeiou]*)' . # odd-numbered vowel
'o' . # even-numbered vowel is o
'(?=[^aeiou]*[aeiou][^aeiou]*$)/', # exactly one more vowel
'$1$2ö',
'heaeafesebatoik');
To do the same but for an odd-numbered o, match 2n leading vowels rather than 2n + 1:
$str = preg_replace(
'/^((?:(?:[^aeiou]*[aeiou]){2})*)' . # 2n vowels, n >= 0
'([^aeiou]*)' . # followed by non-vowels
'o' . # odd-numbered vowel is o
'(?=[^aeiou]*[aeiou][^aeiou]*$)/', # exactly one more vowel
'$1$2ö',
'habatoik');
If one doesn't match, then it performs no replacement, so it's safe to run them in sequence if that's what you're trying to do.
You can use preg_match_all to split the string into vowel/non-vowel parts and process that.
e.g. something like
preg_match_all("/(([aeiou])|([^aeiou]+)*/",
$in,
$out, PREG_PATTERN_ORDER);
Depending on your specific needs, you may need to modify the placement of ()*+? in the regex.
I like to expand on Schmitt. (I don't have enough points to add a comment, I'm not trying to steal his thunder). I would use the flag PREG_OFFSET_CAPTURE as it returns not only the vowels but also there locations. This is my solution:
const LETTER = 1;
const LOCATION = 2
$string = 'heabatoik'
preg_match_all('/[aeiou]/', $string, $in, $out, PREG_OFFSET_CAPTURE);
$lastElement = count($out) - 1; // -1 for last element index based 0
//if second last letter location is even
//and second last letter is beside last letter
if ($out[$lastElement - 1][LOCATION] % 2 == 0 &&
$out[$lastElement - 1][LOCATION] + 1 == $out[$lastElement][LOCATION])
substr_replace($string, 'ö', $out[$lastElement - 1][LOCATION]);
note:
print_r(preg_match_all('/[aeiou]/', 'heabatoik', $in, $out, PREG_OFFSET_CAPTURE));
Array
(
[0] => Array
(
[0] => Array
(
[0] => e
[1] => 1
)
[1] => Array
(
[0] => a
[1] => 2
)
[2] => Array
(
[0] => a
[1] => 4
)
[3] => Array
(
[0] => o
[1] => 6
)
[4] => Array
(
[0] => i
[1] => 7
)
)
)
This is how I would do it:
$str = 'heabatoik';
$vowels = preg_replace('#[^aeiou]+#i', '', $str);
$length = strlen($vowels);
if ( $length % 2 && $vowels[$length - 2] == 'o' ) {
$str = preg_replace('#o([^o]+)$#', 'ö$1', $str);
}