Esto además probablemente llega un poco tarde, pero la forma en que los PHP parse_ini_file obras molestaba tanto que escribí mi propio pequeño analizador.
Siéntase libre de usarlo, pero úselo con cuidado, ¡solo ha sido probado superficialmente!
// the exception used by the parser
class IniParserException extends \Exception {
public function __construct($message, $code = 0, \Exception $previous = null) {
parent::__construct($message, $code, $previous);
}
public function __toString() {
return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
}
}
// the parser
function my_parse_ini_file($filename, $processSections = false) {
$initext = file_get_contents($filename);
$ret = [];
$section = null;
$lineNum = 0;
$lines = explode("\n", str_replace("\r\n", "\n", $initext));
foreach($lines as $line) {
++$lineNum;
$line = trim(preg_replace('/[;#].*/', '', $line));
if(strlen($line) === 0) {
continue;
}
if($processSections && $line{0} === '[' && $line{strlen($line)-1} === ']') {
// section header
$section = trim(substr($line, 1, -1));
} else {
$eqIndex = strpos($line, '=');
if($eqIndex !== false) {
$key = trim(substr($line, 0, $eqIndex));
$matches = [];
preg_match('/(?<name>\w+)(?<index>\[\w*\])?/', $key, $matches);
if(!array_key_exists('name', $matches)) {
throw new IniParserException("Variable name must not be empty! In file \"$filename\" in line $lineNum.");
}
$keyName = $matches['name'];
if(array_key_exists('index', $matches)) {
$isArray = true;
$arrayIndex = trim($matches['index']);
if(strlen($arrayIndex) == 0) {
$arrayIndex = null;
}
} else {
$isArray = false;
$arrayIndex = null;
}
$value = trim(substr($line, $eqIndex+1));
if($value{0} === '"' && $value{strlen($value)-1} === '"') {
// too lazy to check for multiple closing " let's assume it's fine
$value = str_replace('\\"', '"', substr($value, 1, -1));
} else {
// special value
switch(strtolower($value)) {
case 'yes':
case 'true':
case 'on':
$value = true;
break;
case 'no':
case 'false':
case 'off':
$value = false;
break;
case 'null':
case 'none':
$value = null;
break;
default:
if(is_numeric($value)) {
$value = $value + 0; // make it an int/float
} else {
throw new IniParserException("\"$value\" is not a valid value! In file \"$filename\" in line $lineNum.");
}
}
}
if($section !== null) {
if($isArray) {
if(!array_key_exists($keyName, $ret[$section])) {
$ret[$section][$keyName] = [];
}
if($arrayIndex === null) {
$ret[$section][$keyName][] = $value;
} else {
$ret[$section][$keyName][$arrayIndex] = $value;
}
} else {
$ret[$section][$keyName] = $value;
}
} else {
if($isArray) {
if(!array_key_exists($keyName, $ret)) {
$ret[$keyName] = [];
}
if($arrayIndex === null) {
$ret[$keyName][] = $value;
} else {
$ret[$keyName][$arrayIndex] = $value;
}
} else {
$ret[$keyName] = $value;
}
}
}
}
}
return $ret;
}
¿Qué diferencia tiene? Los nombres de las variables solo pueden consistir en caracteres alfanuméricos, pero aparte de eso, no hay restricciones para ellos. Las cadenas deben ser encapsulados con "todo lo demás tiene que ser un valor especial como no
, yes
, true
, false
, on
, off
, null
o none
. Para ver el mapeo de código.
+1 Oh, buena solución :-) – lonesomeday
Gracias, esa es probablemente la única manera de hacerlo. –
¿No se rompería esto si sus valores no son únicos? Después de todo, son * valores *, no claves. – Pacerier