I have this file, I cant figure out how to parse this file.
type = 10
version = 1.2
PART
{
part = foobie
partName = foobie
EVENTS
{
MakeReference
{
active = True
}
}
ACTIONS
{
}
}
PART
{
part = bazer
partName = bazer
}
I want this to be a array which should look like
$array = array(
'type' => 10,
'version' => 1.2,
'PART' => array(
'part' => 'foobie',
'partName' => 'foobie,
'EVENTS' => array(
'MakeReference' => array(
'active' => 'True'
)
),
'ACTIONS' => array(
)
),
'PART' => array(
'part' => 'bazer',
'partName' => 'bazer'
)
);
I tried with preg_match but that was not a success.
Any ideas?
Why not use a format that PHP can decode natively, like JSON?
http://php.net/json_decode
$json = file_get_contents("filename.txt");
$array = json_decode($json);
print_r($array);
Here is my approach.
First of all change Im changing the { to the line before.
Thats pretty easy
$lines = explode("\r\n", $this->file);
foreach ($lines as $num => $line) {
if (preg_match('/\{/', $line) === 1) {
$lines[$num - 1] .= ' {';
unset($lines[$num]);
}
}
Now the input looks like this
PART {
part = foobie
Now we can make the whole thing to XML instead, I know that I said a PHP array in the question, but a XML object is still fine enough.
foreach ($lines as $line) {
if (preg_match('/(.*?)\{$/', $line, $matches)) {
$xml->addElement(trim($matches[1]));
continue;
}
if (preg_match('/\}/', $line)) {
$xml->endElement();
continue;
}
if (strpos($line, ' = ') !== false) {
list($key, $value) = explode(' = ', $line);
$xml->addElementAndContent(trim($key), trim($value));
}
}
The addElement, actually just adds a to a string
endElement adds a and addElementAndContent doing both and also add content between them.
And just for making the whole content being a XML object, im using
$xml = simplexml_load_string($xml->getXMLasText());
And now $xml is a XML object, which is so much easier to work with :)
Related
I have a varying array for a playlist, containing media/source URLs for each item. Like this:
$playlist = array(
array(
"title" => "something",
"sources" => array(
array(
"file" => "https://url.somedomain.com/path/file1.mp3"
)
),
"description" => "somedesc",
"image" => "http://imagepath/",
"file" => "https://url.somedomain.com/path/file1.mp3"
),
array(
"title" => "elsewaa",
"sources" => array(
array(
"file" => "https://url.somedomain.com/someother/file2.mp3"
)
),
"description" => "anotherdesc",
"image" => "http://someotherimagepath/",
"file" => "https://url.somedomain.com/someother/file2.mp3"
)
);
How do I find and replace the values in the file keys to 'randomise' the choice of subdomain?
For example, if the file key contains url.foo.com, how do I replace the url.foo.com portion of the array value with either differentsubdomain.foo.com or anotherplace.foo.com or someotherplace.foo.com?
I was kindly offered a solution for a single string in this question/answer that used str_replace (thanks Qirel!), but I need a solution that tackles the above array configuration specifically.
All the nesting in the array does my head in!
Is it possible to adapt Qirel's suggestion somehow?
$random_values = ['differentsubdomain.foo.com', 'anotherplace.foo.com', 'someotherplace.foo.com'];
$random = $random_values[array_rand($random_values)];
// str_replace('url.foo.com', $random, $file);
If you are just asking how to access members in nested arrays, I think you want this:
$random_values = ['differentsubdomain.foo.com', 'anotherplace.foo.com', 'someotherplace.foo.com'];
// Iterate through the array, altering the items by reference.
foreach ($playlist as &$item) {
$random_key = array_rand($random_values);
$new_domain = $random_values[$random_key];
$item['file'] = str_replace('url.foo.com', $new_domain);
$item['sources'][0]['file'] = str_replace('url.foo.com', $new_domain);
}
Here's an example using recursion to replace the subdomains in any keys named file with a random one.
function replaceUrlHost(&$array, $hostDomain, $subdomains)
{
foreach ($array as $key => $value) {
if (is_array($value)) {
$array[$key] = replaceUrlHost($value, $hostDomain, $subdomains);
continue;
}
if ($key !== 'file') {
continue;
}
$hostname = parse_url($value, PHP_URL_HOST);
if (strpos($hostname, $hostDomain) === false) {
continue;
}
$array[$key] = str_replace(
$hostname,
$subdomains[array_rand($subdomains)] . '.' . $hostDomain,
$value
);
}
return $array;
}
// usage
$subdomains = ['bar', 'baz', 'bing', 'bop'];
$out = replaceUrlHost($playlist, 'somedomain.com', $subdomains);
I am trying to convert a multidimensional array into a string.
Till now I have been able to convert a pipe delimited string into an array.
Such as:
group|key|value
group|key_second|value
Will render into the following array:
$x = array(
'group' => array(
'key' => 'value',
'key_second' => 'value'
),
);
However, now I want it to be the other way around, where a multidimensional array is provided and I want to convert it to a pipe delimited string just like in the first code example.
Any ideas how to do this ?
PS: Please do note that the array can dynamically have any depth.
For example:
$x['group']['sub_group']['category']['key'] = 'value'
Translates to
group|sub_group|category|key|value
I have created my own function:
This should have no problem handling even big arrays
function array_to_pipe($array, $delimeter = '|', $parents = array(), $recursive = false)
{
$result = '';
foreach ($array as $key => $value) {
$group = $parents;
array_push($group, $key);
// check if value is an array
if (is_array($value)) {
if ($merge = array_to_pipe($value, $delimeter, $group, true)) {
$result = $result . $merge;
}
continue;
}
// check if parent is defined
if (!empty($parents)) {
$result = $result . PHP_EOL . implode($delimeter, $group) . $delimeter . $value;
continue;
}
$result = $result . PHP_EOL . $key . $delimeter . $value;
}
// somehow the function outputs a new line at the beginning, we fix that
// by removing the first new line character
if (!$recursive) {
$result = substr($result, 1);
}
return $result;
}
Demo provided here http://ideone.com/j6nThF
You can also do this using a loop like this:
$x = array(
'group' => array(
'key' => 'value',
'key_second' => 'value'
)
);
$yourstring ="";
foreach ($x as $key => $value)
{
foreach ($x[$key] as $key2 => $value2)
{
$yourstring .= $key.'|'.$key2.'|'.$x[$key][$key2]."<BR />";
}
}
echo $yourstring;
Here is a working DEMO
This code should do the thing.
You needed a recursive function to do this. But be careful not to pass object or a huge array into it, as this method is very memory consuming.
function reconvert($array,$del,$path=array()){
$string="";
foreach($array as $key=>$val){
if(is_string($val) || is_numeric($val)){
$string.=implode($del,$path).$del.$key.$del.$val."\n";
} else if(is_bool($val)){
$string.=implode($del,$path).$del.$key.$del.($val?"True":"False")."\n";
} else if(is_null($val)){
$string.=implode($del,$path).$del.$key.$del."NULL\n";
}else if(is_array($val)=='array') {
$path[]=$key;
$string.=reconvert($val,$del,$path);
array_pop($path);
} else {
throw new Exception($key." has type ".gettype($val).' which is not a printable value.');
}
}
return $string;
}
DEMO: http://ideone.com/89yLLo
You can do it by
Look at serialize and unserialize.
Look at json_encode and json_decode
Look at implode
And Possible duplicate of Multidimensional Array to String
You can do this if you specifically want a string :
$x = array(
'group' => array(
'key' => 'value',
'key_second' => 'value'
),
'group2' => array(
'key2' => 'value',
'key_second2' => 'value'
),
);
$str='';
foreach ($x as $key=>$value)
{
if($str=='')
$str.=$key;
else
$str.="|$key";
foreach ($value as $key1=>$value1)
$str.="|$key1|$value1";
}
echo $str; //it will print group|key|value|key_second|value|group2|key2|value|key_second2|value
Here is the working script with hard coded values:
$subject->currentCert['tbsCertificate']['extensions'][] = array(
'extnId' => 'id-ce-subjectAltName',
'critical' => false,
'extnValue' => array(
array('dNSName' => 'www.domain1.com'),
array('dNSName' => 'www.domain2.com')
)
);
I would like to update the above script (extnValue section only) to automatically take values from a another array called $OPTIONS["altnames"]
First I convert the following string to an array
$sans = 'www.domain1.com, www.domain2.com';
I converted the string to an array $OPTIONS["altnames"] with the following code:
$OPTIONS["altnames"] = array();
if ( !empty($sans) ) {
if (strpos($sans,",") !== false) {
$sans = str_replace(" ", "", $sans); //remove spaces
$sans = explode(",", $sans); //strip each value after comma to array
foreach ($sans as $value) {
array_push($OPTIONS["altnames"], $value);
}
}
}
Not sure what to do next
You need to add another level of array in the extnValue array when you copy it from $OPTIONS['altnames']:
$extnValues = array();
foreach ($OPTIONS['altnames'] AS $name) {
$extnValues[] = array('dNSName' => $name);
}
$subject->currentCert['tbsCertificate']['extensions'][] = array(
'extnId' => 'id-ce-subjectAltName',
'critical' => false,
'extnValue' => $extnValues
);
I'm reformulating one of my old programs and using TextCrawler to automate text replacements in several code files, but I'm struggling to make the following change:
I need to find all 'text' functions (example):
$object->text('TRANSLATE_KEY_A')
$object->text('TRANSLATE_KEY_B')
...
and replace them with (example):
__('RETURNED_TEXT_FROM_TRANSLATE_KEY_A', TEXT_DOMAIN)
__('RETURNED_TEXT_FROM_TRANSLATE_KEY_B', TEXT_DOMAIN)
...
Where RETURNED_TEXT_FROM_TRANSLATE_KEY_X are set with the 'text' array's key in another code file
array_push($text, array('key' => 'TRANSLATE_KEY_A',
'extras' => '',
'text' => 'Translated Text A'));
array_push($text, array('key' => 'TRANSLATE_KEY_B',
'extras' => '',
'text' => 'Translated Text B'));
The final result should be:
$object->text('TRANSLATE_KEY_A')
$object->text('TRANSLATE_KEY_B')
...
replaced with
__('Translated Text A', TEXT_DOMAIN)
__('Translated Text B', TEXT_DOMAIN)
...
There are over 1500 of these :(
Is it possible to achieve this with regular expression in TextCrawler, and how? Or any other idea? Thanks
If you want to use a php array to provide the replacement data it is probably best to just use php itself for the task.
Example script.php:
// your $text array
$text = array();
array_push($text, array(
'key' => 'TRANSLATE_KEY_A',
'extras' => '',
'text' => 'Translated Text A')
);
array_push($text, array(
'key' => 'TRANSLATE_KEY_B',
'extras' => '',
'text' => 'Translated Text B')
);
...
// create a separate array from your $text array for easy lookup
$data_arr = array();
foreach ($text as $val) {
$data_arr[$val['key']] = $val['text'];
}
// your code file, passed as first argument
$your_code_file = $argv[1];
// open file for reading
$fh = fopen($your_code_file, "r");
if ($fh) {
while (($line = fgets($fh)) !== false) {
// check if $line has a 'text' function and if the key is in $data_arr
// if so, replace $line with the __(...) pattern
if (preg_match('/^\$object->text\(\'([^\']+)\'\)$/', $line, $matches)
&& isset($data_arr[$matches[1]])) {
printf("__('%s', TEXT_DOMAIN)\n", $data_arr[$1]);
} else {
print($line);
}
}
fclose($fh);
} else {
print("error while opening file\n");
}
Call:
php script.php your_code_file
Just add functionality to iterate over all of your code files and write to the corresponding output files.
I have this OUTPUT array from Decode function down:
Array ( [
] =>
[HostName] => Survival4fun
[GameType] => SMP
[Version] => 1.5.2
[Plugins] => Array
(
[0] => WorldEdit
)
[Map] => world
[Players] => 0
[MaxPlayers] => 10
[HostPort] => 25608
[HostIp] => 31.133.13.99
[RawPlugins] => WorldEdit5.5.6;
[Software] => CraftBukkitonBukkit1.5.2-R0.1
[Status] => online
[Ping] => 15ms
[
] =>
[PlayersOnline] => Array
(
[P0] => NoPlayers
)
[
] => )
And so, you can see this:
[
] =>
How can I remove it ? I tried using str_replace("\n", "", $arr); But this doesn't work.
Here is the original array - http://status.mc-host.cz/s8.mc-host.cz:25608-feed
And here is my function code:
Function Decode_query($link) {
$data = file($link, FILE_IGNORE_NEW_LINES);
$arr = array();
$string = array("[", "]", " ", "(", ")", "Array", "\n", "\r");
$replace = array("", "", "", "", "", "", "", "");
ForEach ($data as $line) {
$s = str_replace($string, $replace, $line);
If (Empty($s)) {} Else {
$stat = explode("=>", $s);
$P = str_replace("P", "", $stat[0]);
If (is_numeric($stat[0])) {
$arr["Plugins"][$stat[0]] = $stat[1];
}
ElseIf (is_numeric($P)) {
$arr['PlayersOnline'][$stat[0]] = $stat[1];
} Else {
$arr[$stat[0]] = $stat[1];
}
}
}
Return $arr;
}
$arr = Decode_query("http://status.mc-host.cz/s8.mc-host.cz:25608-feed");
Print_r($arr);
Thanks for help and sorry for long question..
You could use a regex to scan for keys that are composed of only whitespace:
$keys = array_keys($your_array);
$blank_keys = preg_grep('/^\s*$/', $keys);
foreach($blank_keys as $blank) {
unset($your_array[$blank]);
}
I would work with trim in stead of str_replace. It is less expensive, and it takes care of the trailing spaces and whatever whitespace there may be. In your case your function would probably look something like this:
Function Decode_query($link) {
// fetch the data
$data = file($link, FILE_IGNORE_NEW_LINES);
// prepare output array
$arr = array('Plugins' => array(), 'PlayersOnline' => array());
// prepare the list of characters we want to remove
$removeChars = ' \t\n\r[]';
ForEach ($data as $line) {
// split line into key, value
$stat = explode("=>", $line);
// no 2 elements, means no '=>', so ignore line
if (count($stat) < 2) continue;
// remove unwanted characters from key
$trimmed = trim($stat[0], $removeChars);
$pTrimmed = trim($trimmed, 'P');
// if key = plugins, ignore line
if ($trimmed == 'Plugins') continue;
// if key is numeric
If (is_numeric($trimmed)) {
// store in plugins subarray
$arr['Plugins'][$trimmed] = trim($stat[1]);
}
// if (key - P) is numeric
ElseIf (is_numeric($pTrimmed)) {
// store in players online subarray
$arr['PlayersOnline'][$pTrimmed] = trim($stat[1]);
} Else {
// all others store in level 1 array
$arr[$trimmed] = trim($stat[1]);
}
}
Return $arr;
}
I didn't test the code, but I think it should work fine.
PS: You can never put enough comments in your code, may seem a waste of time at first, but you, or anyone who has to work on your code, will be very grateful some day...