abel
abel

Reputation: 2383

Regex for Reading ini with PHP

Sample ini file is

[SAMPLE.jpg]
faces=rect64(c18f4c8ef407851e),d4ff0a020be5c3c0;rect64(534a06d429ae627),dff6163dfd9d4e41;rect64(b9c100fae46b3046),e1059dcf6672a2b3;rect64(7b5105daac3a3cf4),4fc7332c107ffafc;rect64(42a036a27062a6c),ef86c3326c143248;rect64(31f4efe3bd68fd8),90158b3d3b65dc9b;rect64(327904e0614d390d),43cbda6e92fcb63e;rect64(4215507584ae9b8c),15b6a967e857f334;rect64(895d4efeb8b68425),5c4ff70ac70b27d3
backuphash=285
[Size.JPG]
faces=rect64(f73101cd554ca7f),43cbda6e92fcb63e
backuphash=38150
[ints.jpg]
faces=rect64(45c213047999593c),e1059dcf6672a2b3
backuphash=19801
[SC.jpg]
faces=rect64(993f2dfdab7f5166),e1059dcf6672a2b3;rect64(4b002f365a004c1b),ef86c3326c143248;rect64(bbffbb9fcb7fda25),ef86c3326c143248;rect64(bbbf9b10cb7fb996),90158b3d3b65dc9b;rect64(bbffdc97cb3ffa4c),4fc7332c107ffafc;rect64(5ec0306f734058b9),43cbda6e92fcb63e;rect64(65c06969827fa12b),15b6a967e857f334;rect64(bbff59f2cbbf7878),15b6a967e857f334;rect64(bbff7a81cb3f989f),43cbda6e92fcb63e
backuphash=9829
[karate.jpg]
faces=rect64(20823e7a6186b30b),15b6a967e857f334;rect64(92cb3e7ad34cb30b),15b6a967e857f334
backuphash=34154

Algorithm for pattern

[$name_of_picture]
faces=rect64($hex1_1),$hex1_2;rect64($hex2_1),hex2_2;....rect64($hexn_1),hexn_2;

I am interested in reading only the parts that are assigned by $var_name.. in the above code. How do I go about it?

Update

Using parse ini

<?php
//code from php.net

// Parse without sections
$ini_array = parse_ini_file("pic.ini");
print_r($ini_array);

// Parse with sections
$ini_array = parse_ini_file("pic.ini", true);
print_r($ini_array);

?>

Output

Warning: parse error in pic.ini on line 2 in C:\tezt\up.php on line 26

Warning: parse error in pic.ini on line 2 in C:\tezt\up.php on line 30

Update2

<?php

function new_parse_ini($f)
{

    // if cannot open file, return false
    if (!is_file($f))
        return false;

    $ini = file($f);

    // to hold the categories, and within them the entries
    $cats = array();

    foreach ($ini as $i) {
        if (@preg_match('/\[(.+)\]/', $i, $matches)) {
            $last = $matches[1];
        } elseif (@preg_match('/(.+)=(.+)/', $i, $matches)) {
            $cats[$last][$matches[1]] = $matches[2];
        }
    }

    return $cats;

}

?>

Output

Array ( [SAMPLE.jpg] => Array ( [faces] => rect64(c18f4c8ef407851e),d4ff0a020be5c3c0;rect64(534a06d429ae627),dff6163dfd9d4e41;rect64(b9c100fae46b3046),e1059dcf6672a2b3;rect64(7b5105daac3a3cf4),4fc7332c107ffafc;rect64(42a036a27062a6c),ef86c3326c143248;rect64(31f4efe3bd68fd8),90158b3d3b65dc9b;rect64(327904e0614d390d),43cbda6e92fcb63e;rect64(4215507584ae9b8c),15b6a967e857f334;rect64(895d4efeb8b68425),5c4ff70ac70b27d3 [backuphash] => 285 ) [Size.JPG] => Array ( [faces] => rect64(f73101cd554ca7f),43cbda6e92fcb63e [backuphash] => 38150 ) [ints.jpg] => Array ( [faces] => rect64(45c213047999593c),e1059dcf6672a2b3 [backuphash] => 19801 ) [SC.jpg] => Array ( [faces] => rect64(993f2dfdab7f5166),e1059dcf6672a2b3;rect64(4b002f365a004c1b),ef86c3326c143248;rect64(bbffbb9fcb7fda25),ef86c3326c143248;rect64(bbbf9b10cb7fb996),90158b3d3b65dc9b;rect64(bbffdc97cb3ffa4c),4fc7332c107ffafc;rect64(5ec0306f734058b9),43cbda6e92fcb63e;rect64(65c06969827fa12b),15b6a967e857f334;rect64(bbff59f2cbbf7878),15b6a967e857f334;rect64(bbff7a81cb3f989f),43cbda6e92fcb63e [backuphash] => 9829 ) [karate.jpg] => Array ( [faces] => rect64(20823e7a6186b30b),15b6a967e857f334;rect64(92cb3e7ad34cb30b),15b6a967e857f334 [backuphash] => 34154 ) )

So far so good. Thank you guys. This question is related to another question of mine Automatic face detection using Picasa API to extract individual images

Upvotes: 1

Views: 2154

Answers (6)

countach
countach

Reputation: 605

My function is based on OP's one, but is fixed in some points. It parses a .ini text contents into an array. It handles no category values, properly treats de quotes around values and allows empty lines, for example.

function stripQuotes($text) {
    return preg_replace('/^(\'(.*)\'|"(.*)")$/', '$2$3', $text);
}


function ini2array($s) {
    $ini=explode("\n", $s);

    // to hold the categories, and within them the entries
    $cats = array();
    $last = '';

    foreach ($ini as $i) {
        if (@preg_match('/\[(.+)\]/', $i, $matches)) {
            $last=stripQuotes(trim($matches[1]));
        } elseif (@preg_match('/(.+)=(.+)/', $i, $matches)) {
            $key=stripQuotes(trim($matches[1]));
            if (strlen($key)>0) {
                $val=stripQuotes(trim($matches[2]));
                if (strlen($last) > 0) {
                    $cats[$last][$key]=trim($val);
                } else {
                    $cats[$key]=trim($val);
                }
            }
        }
    }

    return $cats;
}

Upvotes: 0

kenorb
kenorb

Reputation: 166667

Please check the following ini regex from drush tool:

class ParserIni implements ParserInterface {
  /**
   * Regex for parsing INI format.
   */
  private static $iniRegex = '
    @^\s*                           # Start at the beginning of a line, ignoring leading whitespace
    ((?:
      [^=;\[\]]|                    # Key names cannot contain equal signs, semi-colons or square brackets,
      \[[^\[\]]*\]                  # unless they are balanced and not nested
    )+?)
    \s*=\s*                         # Key/value pairs are separated by equal signs (ignoring white-space)
    (?:
      ("(?:[^"]|(?<=\\\\)")*")|     # Double-quoted string, which may contain slash-escaped quotes/slashes
      (\'(?:[^\']|(?<=\\\\)\')*\')| # Single-quoted string, which may contain slash-escaped quotes/slashes
      ([^\r\n]*?)                   # Non-quoted string
    )\s*$                           # Stop at the next end of a line, ignoring trailing whitespace
    @msx';

  /**
   * {@inheritdoc}
   */
  public static function parse($data) {
    if (preg_match_all(self::$iniRegex, $data, $matches, PREG_SET_ORDER)) {
      $info = array();
      foreach ($matches as $match) {
        // Fetch the key and value string.
        $i = 0;
        foreach (array('key', 'value1', 'value2', 'value3') as $var) {
          $$var = isset($match[++$i]) ? $match[$i] : '';
        }
        $value = stripslashes(substr($value1, 1, -1)) . stripslashes(substr($value2, 1, -1)) . $value3;
        // Parse array syntax.
        $keys = preg_split('/\]?\[/', rtrim($key, ']'));
        $last = array_pop($keys);
        $parent = &$info;
        // Create nested arrays.
        foreach ($keys as $key) {
          if ($key == '') {
            $key = count($parent);
          }
          if (isset($merge_item) && isset($parent[$key]) && !is_array($parent[$key])) {
            $parent[$key] = array($merge_item => $parent[$key]);
          }
          if (!isset($parent[$key]) || !is_array($parent[$key])) {
            $parent[$key] = array();
          }
          $parent = &$parent[$key];
        }
        // Handle PHP constants.
        if (defined($value)) {
          $value = constant($value);
        }
        // Insert actual value.
        if ($last == '') {
          $last = count($parent);
        }
        if (isset($merge_item) && isset($parent[$last]) && is_array($parent[$last])) {
          $parent[$last][$merge_item] = $value;
        }
        else {
          $parent[$last] = $value;
        }
      }
      return $info;
    }
  }
}

Then use it like:

$parsed = ParserIni::parse($data);

Upvotes: 0

Vantomex
Vantomex

Reputation: 2295

In case you are curious how to parse it with regex, or maybe you are lazy to write relatively long code, here it is using regex:

^\s*\[([^\]]+)\]

You can refer to text inside the square-brackets using $1 in replace part, or \1 if you refer to in search part.

However, I agree you should use built-in PHP library for parsing INI files for serious projects.

Upvotes: 1

jensgram
jensgram

Reputation: 31498

To elaborate on Pekka's answer:

  1. Parse file via $ini = parse_ini_file(<file>, true)
  2. Select faces=... by image name: $str = $ini[$name_of_picture]['faces']
  3. explode() on ;
  4. Iterate those and explode on ,

(You may want to make sure that the section ($name_of_picture) and directive (faces) exist, see isset().)

Upvotes: 2

Andy Lester
Andy Lester

Reputation: 93725

Not everything related to strings is best answered with a regex.

In this case, you have functionality built in to PHP that does this for you.

http://php.net/manual/en/function.parse-ini-file.php

Upvotes: 2

Pekka
Pekka

Reputation: 449613

PHP has a built-in function for parsing INI files. parse_ini_file()

Upvotes: 7

Related Questions