PHP - array filled with stdin integer input - php

Example :
$_fp = fopen("file.txt", "r");
/* STDIN = "4 7 6 24 1"; */ <== user input
$input[] = fgets($_fp);
print_r($input);
OUTPUT :
Array
(
[0] => 4 7 6 24 1
)
Desired OUTPUT :
Array
(
[0] => 4
[1] => 7
[2] => 6
[3] => 24
[4] => 1
)
Is there any method to remove spaces from integer input after entering each to an array?
In a way to avoid having the whole input as one single line.
i used $input[] = explode(' ', trim(fgets($_fp))); now when there is second line it only puts the first line of the STDIN i need to read all lines and put them into the input variable
while($f = fgets(STDIN)){ echo "line: $f"; } is great use here
it is fine for echoing all lines but cant assign each line to a variable or array yet.. not sure if i should array_push() since i need 2 lines as variables and rest as arrays..

use trim remove the "\n" of the line, the use explode to convert it to array.
Live Demo
$input = explode(' ', trim(fgets($_fp)));
if you has more lines, use below:
$input[] = explode(' ', trim(fgets($_fp)));

Even we can try preg_match_all with regx also give same result with all cases like what if you have double space or any text between the interger strings
$string = "4 7 6 24 1";
$string = "4 test df 7 6 24 1";
$string = "4 7 6 24 1";
preg_match_all('!\d+!', $string, $matches);
print_r($matches);

Related

Exclude text to valid array

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

Convert a collection of numbers as string to numbers

If I have a string as : 10 20 3 4 15 6
How can I convert it to individual numbers and store it in a array?
PHP is very clever when dealing with types of variables. You don't need it to be an integer, it can be a string of numbers, and PHP would still treat it as integers when performing operations on them.
If you want to have each element be the numbers separated by spaces, you simply do
$array = explode(" ", "10 20 3 4 15 6");
The output of $array would then be
Array (
[0] => 10
[1] => 20
[2] => 3
[3] => 4
[4] => 15
[6] => 6
)
Live demo
$str = "10 20 3 4 15 6";
$arr = str_split($str);
$intArr = array_map('intval', $arr);
Might be a better way of doing it but the above should do the work.

Regex for PHP preg_replace to find numbers between tags

I know it's naive question, but regex is always confusing for me.
I want to replace numbers in a string if they are between a tag, here parenthesis.
$str = " Some text 11 have number 12 (11,12,13)";
$array = array( 1 => 'one', 2 => 'two', 11 => 'eleven', 12 => 'twelve', 13 => 'thirteen');
foreach ($array as $key => $value) {
$str = preg_replace( 'regex to match $key', $value, $str);
}
The result should be
$str = " Some text 11 have number 12 (eleven,twelve,thirteen)";
I am struggling with regex pattern to match number which should be within parenthesis. Inside the parenthesis is only numbers and ,.
I suggest using a regex that finds all consecutive numbers (digit chunks) separated with a comma after an opening (. Then, the matches can be passed to a preg_replace_callback and if the corresponding key is present in the array, replace it with the corresponding value, else, just put the match back.
Here is the regex:
(?:\G(?!\A)|\(),?\K\d+
See regex demo
Details:
(?:\G(?!\A)|\() - Matches either the position of the previous successful match (\G(?!\A)) or a ( symbol
,? - an optional (1 or 0) comma
\K - an operator discarding all the text matched so far
\d+ - 1 or more digits (the only text we have in the match returned).
And here is the PHP code:
$re = '/(?:\G(?!\A)|\(),?\K\d+/';
$str = "Some text 11 have number 12 (9,11,12,13)";
$array = array( 11 => 'eleven', 12 => 'twelve', 13 => 'thirteen');
echo $result = preg_replace_callback($re, function ($m) use ($array) {
return !empty($array[$m[0]]) ? $array[$m[0]] : $m[0];
}, $str) . PHP_EOL;
The result is Some text 11 have number 12 (9,eleven,twelve,thirteen) as 9 is missing in the $array.
I'd use preg_replace_callback. Then you can use \(([\d\h,]+)\) which checks for numbers, horizontal spaces, or commas inside () and captures all found values. The function then uses str_replace to replace them.
$string = " Some text 11 have number 12 (11,12,13)";
$array = array( 11 => 'eleven', 12 => 'twelve', 13 => 'thirteen');
echo preg_replace_callback('/\(([\d\h,]+)\)/', function ($matches) use ($array) {
return str_replace(array_keys($array), array_values($array), $matches[1]);
}, $string);
Demo: https://eval.in/589888
You can try this:
$str = " Some text 11 have number 12 (11,12,13)";
$array = array( 11 => 'eleven', 12 => 'twelve', 13 => 'thirteen');
foreach ($array as $key => $value) {
$str = preg_replace('/(\(|,)' . $key . '(\)|,)/', "$1" . $value . "$2", $str);
}
And when you var_dump($str):
string(53) " Some text 11 have number 12 (eleven,twelve,thirteen)"

Split file up based on delimiters in php - which is the best to use?

I am trying to parse a file using php but I am not sure of the best way to do it. The file consists of stuff like:
saturn+5 57 space+shuttle 34 gemini 12 mercury 2 soyuz+tm 1
What I'm trying to do is split it up and populate a hash map, so..
$inventory["saturn+5"] = "57";
$inventory["space+shuttle"] = "34";
and so on.
I don't know how to tackle this.
I am trying to write a bit of regex to process the file to separate out the fields but I'm not having much luck and was wondering if I should try using a different approach using split() or explode().
Here's my approach using regular expression.
$data = 'saturn+5 57 space+shuttle 34 gemini 12 mercury 2 soyuz+tm 1';
$inventory = array();
preg_match_all('/(\S+) (\S+)/', $data, $matches);
foreach ($matches[1] as $index => $match) {
$inventory[$match] = $matches[2][$index];
}
print_r($inventory);
Output
Array
(
[saturn+5] => 57
[space+shuttle] => 34
[gemini] => 12
[mercury] => 2
[soyuz+tm] => 1
)
my crude approach:
<?php
echo '<pre>';
$str="saturn+5 57 space+shuttle 34 gemini 12 mercury 2 soyuz+tm 1";
//break it on space
$e=explode(' ',$str);
//reindex array to start from 1
array_unshift($e, "phoney");
unset($e[0]);
print_r($e);
$inventory=array();
foreach ($e as $k=>$v){
//detects odd key
if(($k+2)%2==1) {
$inventory[$v]= $e[$k+1];
}
}
print_r($inventory);
demo: http://codepad.viper-7.com/PN6K8m
output:
Array
(
[saturn+5] => 57
[space+shuttle] => 34
[gemini] => 12
[mercury] => 2
[soyuz+tm] => 1
)
It's actually quite trivial with a regex:
preg_match_all("/ ([\w+]+) \s (\d+) /x", $string, $m);
$assoc = array_combine($m[1], $m[2]);
You're just looking for a combination of alphanumeric characters \w and optional + signs, then a space, then a \d decimal.
array_combine will give you the associative array.
If it's always in that order, this will work:
<?
$foo = 'saturn+5 57 space+shuttle 34 gemini 12 mercury 2 soyuz+tm 1';
$foo_array = preg_split('/\s+/', $foo);
$hash = array();
for ($i = 0; $i < count($foo_array); $i++){
$i % 2 ? null : $hash[$foo_array[$i]] = $foo_array[++$i];
}
print_r($hash);
?>
Output:
php foo.php
Array
(
[saturn+5] => 57
[space+shuttle] => 34
[gemini] => 12
[mercury] => 2
[soyuz+tm] => 1
)

String parser/separation in PHP

I have data which I wish to be pasted into a textbox, it will be in the form E.G
Ryu Aiter D78:21:87:13 177 /177 1 / 6
Ryu Chronos D78:21:26:21 182 /182 0 / 6
Ryu Hermes D78:21:26:22 201 /201 0 / 6
Ryu Hefaistos D78:31:75:10 136 /136 1 / 2
Ryu Krotos D78:84:96:11 170 /170 1 / 6
Ryu Heros D78:65:51:31 175 /175 2 / 5
Ryu Arachnos D78:13:84:11 185 /185 0 / 5
its splits up like this
Base(max 16 chars)
Location(staring D , 12 chars)
econ/max econ (int/int)
used/Total(int/int)
What i wish to do is create a loop for each Row of text,
and then inside that loop chop out each part of the row into variables for each component.
as far as ideas on separating it i know that the : symbol is banned from names and bases.
so if i find the first ":" then step back 2 and take the next 12 chars that is my location
i know that can be done with a until loop and if(string[x]=':')
But how do i loops through rows?
And how can i separate the rest of the data in a row?
This is what regular expressions are for :P try this out:
$lines = explode( "\r\n", $data );
$users = array();
foreach( $lines as $line )
{
$matches = array();
$user = array();
preg_match( "/([^ ]+) ([^ ]+) ((?:[A-Z])(?:[0-9]+:){3}[0-9]+) ([0-9]+) \/([0-9]+) ([0-9]+) \/ ([0-9]+)/", $line, $matches );
list(,$user['name'],$user['base'],$user['location'],$user['econ'],$user['maxecon'],$user['used'],$user['total']) = $matches;
$users[] = $user;
}
You will have an array called users which contains a series of associative arrays with the components. Like below...
Array
(
[0] => Array
(
[total] => 6
[used] => 1
[maxecon] => 177
[econ] => 177
[location] => D78:21:87:13
[base] => Aiter
[name] => Ryu
)
[1] => Array
(
[total] => 6
[used] => 0
[maxecon] => 182
[econ] => 182
[location] => D78:21:26:21
[base] => Chronos
[name] => Ryu
)
etc, etc...
EDIT: I made a lot of assumptions about the data as you haven't given many details, if you need further help with the expression let me know.
UPDATE AS PER YOUR COMMENT:
Line 182: $name = htmlspecialchars(mysql_real_escape_string($_POST['name']));
Line 188: $tecon = htmlspecialchars(mysql_real_escape_string($user['econ']));
You should turn on display_errors as they were simple syntax errors that could easily be debugged.
Can you just use explode and gradually break it down?
eg.
explode the entry into seperate lines at '\n'
then explode each line into 2, everything before the 1st ':', and everything after
explode the 1st part into pieces using each 'space' to give you Name, Base, Location
explode the 2nd part using 'space', ':' or '/' to give you econ/max econ and used/Total
if(preg_match_all('/^([a-z]{1,16})\s+([a-z]{1,16})\s+(D\d+):(\d+):(\d+):(\d+)\s+(\d+)\s+\/(\d+)\s+(\d+)\s+\/\s+(\d+)$/mi', $yourinputgoeshere, $match) {
print_r($match);
}
This should, untested, get everything into a large array, separated. Untested
Extending the same idea i am trying to use preg match for a single line on another page.
i use the code
$data = $_POST['list'];
$matches = array();
$user = array();
preg_match( "/(.+?) ((?:[A-Z])(?:[0-9]+:){3}[0-9]+) ([0-9]+) \/([0-9]+) ([0-9]+) \/ ([0-9]+)/", $data, $matches );
list(,$user['base'],$user['location'],$user['econ'],$user['maxecon'],$user['used'],$user['total']) = $matches;
$base = $users['base'];
$location = $users['location'];
$tecon = $users['econ'];
i used echo to print out £data and it contains the data as expected but the same code without the lines loop does not seperate the parts of my data into the array..in fact the array size of $user remains empty, what has gone wroung?

Categories